首页 > 解决方案 > python列表理解与cls

问题描述

我遇到了如下代码片段:

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

我对两点感到困惑:

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

我相信这段代码是由比我更熟悉python的人编写的,我相信他这样做一定有一些理由......

标签: pythonlistclasslist-comprehension

解决方案


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,但也可以返回字母的索引或第一个大写实例的索引。


推荐阅读