简体   繁体   English

python 与 cls 的列表理解

[英]python list comprehension with cls

I encountered a snippet of code like the following:我遇到了如下代码片段:

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

I'm confusing for two points:我对两点感到困惑:

  1. what does [... for cls in array] mean, since cls is a reserved keyword for class , why not just using [... for s in array] ? [... for cls in array]是什么意思,因为clsclass的保留关键字,为什么不直接使用[... for s in array]
  2. why bother to write something complicated like this instead of just [i for i in range(len(array))] .为什么要写这样复杂的东西,而不仅仅是[i for i in range(len(array))]

I believe this code is written by someone more experienced with python than me, and I believe he must have some reason for doing so...我相信这段代码是由比我更有经验的 python 编写的,我相信他这样做一定有一些理由......

cls is not a reserved word for class . cls不是class的保留字。 That would be a very poor choice of name by the language designer.这对于语言设计者来说是一个非常糟糕的名称选择。 Many programmers may use it by convention but it is no more reserved than the parameter name self .许多程序员可能会按照惯例使用它,但它并不比参数名称self保留更多。

If you use distinct upper and lower case characters in the list, you will see the difference:如果您在列表中使用不同的大写和小写字符,您将看到不同之处:

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

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

The value at position 3 is 1 instead of 3 because the first occurrence of a lowercase 'B' is at index 1. Similarly, the value at the last positions is 2 instead of 5 because the first 'c' is at index 2. position 3 处的值是 1 而不是 3,因为小写字母“B”的第一次出现在索引 1 处。类似地,最后位置的值是 2 而不是 5,因为第一个“c”在索引 2 处。

This list comprehension requires that the array always contain a lowercase instance of every uppercase letter.此列表理解要求数组始终包含每个大写字母的小写实例。 For example ['a', 'B', 'c'] would make it crash.例如['a', 'B', 'c']会使它崩溃。 Hopefully there are other safeguards in the rest of the program to ensure that this requirement is always met.希望程序的 rest 中还有其他保护措施,以确保始终满足此要求。

A safer, and more efficient way to write this would be to build a dictionary of character positions before going through the array to get indexes.一种更安全、更有效的编写方法是在通过数组获取索引之前构建一个字符位置字典。 This would make the time complexity O(n) instead of O(n^2).这将使时间复杂度 O(n) 而不是 O(n^2)。 It could also help make the process more robust.它还可以帮助使流程更加稳健。

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]

The firstchar dictionary contains the first index in array containing a given letter. firstchar字典包含array中包含给定字母的第一个索引。 It is built by going backward through the array so that the smallest index remains when there are multiple occurrences of the same letter.它是通过向后遍历数组来构建的,因此当同一个字母多次出现时,最小的索引仍然存在。

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

Then, going through the array to form ids , each character finds the corresponding index in O(1) time by using the dictionary.然后,遍历数组形成ids ,每个字符使用字典在 O(1) 时间内找到对应的索引。

Using the .get() method allows the list comprehension to survive an upper case letter without a corresponding lowercase value in the list.使用.get()方法允许列表推导在列表中没有对应的小写值的情况下保留大写字母。 In this example it returns None but it could also be made to return the letter's index or the index of the first uppercase instance.在此示例中,它返回None但也可以返回字母的索引或第一个大写实例的索引。

Some developers might be experienced, but actually terrible with the code they write and just "skate on by".一些开发人员可能经验丰富,但实际上他们编写的代码很糟糕,只是“溜冰”。

Having said that, your suggested output for question #2 would differ if the list contained two of any element.话虽如此,如果列表包含任何元素中的两个,您为问题 #2 建议的 output 会有所不同。 The suggested code would return the first indices where a list element occurs where as yours would give each individual items index.建议的代码将返回列表元素出现的第一个索引,您的代码将给出每个单独的项目索引。 It would also differ if the array elements weren't lowercase.如果array元素不是小写,它也会有所不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM