【问题标题】:python list comprehension with clspython列表理解与cls
【发布时间】:2023-03-29 23:35:02
【问题描述】:

我遇到了一段类似如下的sn-p代码:

array = ['a', 'b', 'c']
ids = [array.index(cls.lower()) for cls in array]

我对两点感到困惑:

  1. [... for cls in array] 是什么意思,既然clsclass 的保留关键字,为什么不直接使用[... for s in array]
  2. 何必写这么复杂的东西,而不是[i for i in range(len(array))]

我相信这段代码是由比我更熟悉python的人写的,我相信他这样做一定是有原因的……

【问题讨论】:

  • 简单的回答是程序员的素质参差不齐
  • 经验 != 质量
  • 吹毛求疵,但cls 不是保留关键字,只是一个约定。

标签: python list class list-comprehension


【解决方案1】:

cls 不是class 的保留字。这对于语言设计者来说是一个非常糟糕的名称选择。许多程序员可能会按照约定使用它,但它并不比参数名称self 保留更多。

如果您在列表中使用不同的大小写字符,您会看到区别:

array = ['a', 'b', 'c', 'B','A','c']
ids = [array.index(cls.lower()) for cls in array]
print(ids)

[0, 1, 2, 1, 0, 2]

位置 3 的值是 1 而不是 3,因为第一次出现的小写字母“B”在索引 1 处。类似地,最后位置的值是 2 而不是 5,因为第一个“c”在索引处2.

此列表解析要求数组始终包含每个大写字母的小写实例。例如['a', 'B', 'c'] 会使它崩溃。希望程序的其余部分有其他保障措施,以确保始终满足此要求。

一种更安全、更有效的编写方法是在通过数组获取索引之前构建一个字符位置字典。这将使时间复杂度 O(n) 而不是 O(n^2)。它还可以帮助使流程更加稳健。

array     = ['a', 'b', 'c', 'B','A','c','Z']
firstchar = {c:-i for i,c in enumerate(array[::-1],1-len(array))}
ids       = [firstchar.get(c.lower()) for c in array]

print(ids)
[0, 1, 2, 1, 0, 2, None]

firstchar 字典包含array 中包含给定字母的第一个索引。它是通过向后遍历数组来构建的,因此当同一个字母多次出现时,最小的索引仍然存在。

{'Z': 6, 'c': 2, 'A': 4, 'B': 3, 'b': 1, 'a': 0}

然后,遍历数组形成ids,每个字符通过字典在O(1)时间内找到对应的索引。

使用.get() 方法允许列表解析在列表中没有对应的小写值的大写字母中保留下来。在本例中,它返回 None,但也可以返回字母的索引或第一个大写实例的索引。

【讨论】:

  • 这里有一个更优雅的方式来构建firstchar,如果你想要的话:firstchar = {}; for i, c in enumerate(array): firstchar.setdefault(c, i)
【解决方案2】:

一些开发人员可能经验丰富,但实际上他们编写的代码很糟糕,只是“溜冰”。

话虽如此,如果列表包含两个任意元素,您对问题 #2 的建议输出会有所不同。建议的代码将返回出现列表元素的第一个索引,而您的代码将给出每个单独的项目索引。如果array 元素不是小写,它也会有所不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 2016-10-04
    • 1970-01-01
    • 2011-09-02
    • 2020-11-09
    • 1970-01-01
    • 2022-12-13
    相关资源
    最近更新 更多