如果你这样做{k:v for k,v in zip(*[iter(x)]*2)}
x
是一个列表,你会得到一个字典,其中包含所有奇数元素作为键,甚至作为它们的值。哇!
>>> x = [1, "cat", "hat", 35,2.5, True]
>>> d = {k:v for k,v in zip(*[iter(x)]*2)}
>>> d
{1: "cat", "hat": 35, 2.5: True}
我基本了解字典理解是如何工作的,zip
如何工作,*
如何提取参数,[iter(x)]*2
如何连接列表的两个副本,所以我期待一个像{1: 1, "cat": "cat" ...}
这样的一对一通信。
这里发生了什么?
答案 0 :(得分:6)
这肯定是一段有趣的小代码!它可能没有预料到的主要因素是对象实际上是通过引用传递的(它们实际上是passed by assignment,但是嘿)。 iter()
构造一个对象,因此“复制”它(在列表中使用乘法,在这种情况下)不会创建一个新对象,而是添加另一个对同一个的引用。这意味着你有一个列表,l[0]
是一个迭代器,l[1]
是相同的迭代器 - 访问它们都访问同一个对象。
每次访问迭代器的下一个元素时,它都会继续它最后一次停止的位置。由于元素在zip()
创建的元组的第一个和第二个元素之间交替访问,因此单个迭代器的状态在元组中的两个元素之间都是高级的。
在那之后,字典理解只会消耗这些对元组,因为它们扩展到k, v
- 就像在任何其他字典理解中一样。
答案 1 :(得分:5)
这个iter(x)
在迭代(列表或类似的)x
上创建一个迭代器。使用[iter(x)]*2
复制此迭代器。现在你有两次相同迭代器的列表。这意味着,如果我向其中一个人询问一个值,另一个(相同的)也会增加。
zip()
现在通过zip(* ... )
语法获得两个参数(它们相同)作为两个参数。这意味着,它创建了一个由它得到的两个参数对的列表。它将向第一个迭代器询问一个值(并接收x[0]
),然后它会向另一个迭代器询问一个值(并接收x[1]
),然后它将形成一对两个值并且把它放在它的输出中。然后它会反复执行此操作,直到迭代器耗尽为止。这样,它将形成一对x[2]
和x[3]
,然后是一对x[4]
和x[5]
等。
然后将这个对列表传递给字典理解,这将把对形成为字典的键/值。
易于阅读可能是这样的:
{ k: v for (k, v) in zip(x[::2], x[1::2]) }
但这可能效率不高。