我了解可以通过以下两种方法创建元组:
tuple([1, 2, 3])
(1, 2, 3)
我试图了解这里到底发生了什么:
tuple( (x, x*x) for x in [1, 2, 3] )
tuple构造函数似乎想要一个列表,但是以下代码似乎不会产生一个列表
(x, x*x) for x in [1, 2, 3]
我也想知道为什么这不起作用:
( (x, x*x) for x in [1, 2, 3] )
使用字典,看来我可以使用其中任何一个:
my_dict = dict()
my_dict = {}
但是现在我想知道是否像元组一样有区别。 ():tuple()
与::
的{{1}}关系是否不同?
答案 0 :(得分:1)
让我们分解一下这里发生的事情。您可以理解,元组构造函数似乎想要一个列表是没有错的,但是更确切地说,元组构造函数似乎想要一个类似列表的对象。 (具体来说,是任何可迭代的作品)
这是称为Duck Typing的哲学。
俗话如下:
如果它走路像鸭子,游泳像鸭子,嘎嘎像鸭子, 那可能是鸭子。
那么,列表就可以了
a = [1, 2, 3, 2]
tuple(a) #Output: (1, 2, 3, 2)
,但是其他可迭代项也是如此,例如set
tuple(set(a)) #Output: (1, 2, 3)
因此,元组不在乎它接收的对象是否是列表,只是它应该能够迭代并从该对象获取值。
现在,魔术的第二部分来自称为列表理解/生成器表达式的东西。您可以创建它们的可迭代项,从而轻松编写1个分别创建列表或生成器表达式的内衬。稍后,更多关于生成器的知识,足以了解列表理解的工作原理。
的简单示例[a for a in range(4)] #Output: [0, 1, 2, 3]
[a*a for a in range(4)] #output: [0, 1, 4, 9]
我们看到他们产生了清单。那么,我们可以将它们提供给元组构造函数吗?为什么不呢!
tuple([a for a in range(4)]) #Output: (0, 1, 2, 3)
tuple([a*a for a in range(4)]) #output: (0, 1, 4, 9)
现在,使用相同的表达式但将其包装在尖括号中怎么办?
(a for a in range(4)) #Output: <generator object <genexpr> at 0x000000FA4FDBE728>
您刚刚创建了generator expression
它们本质上是高效内存的按需迭代。 (具体来说,它们具有yield和next,并且仅根据需要提供yield值)。让我们来看看它的作用。
my_generator = (a for a in range(4)) #generator created.
next(my_generator) #Outputs 0
next(my_generator) #Outputs 1
next(my_generator) #outputs 2
next(my_generator) #outputs 3
next(my_generator) #Raises StopIteration Error. The generator is exhausted.
我们可以看到我们收到的值与列表理解中的值相同。 那么,元组接受诸如生成器之类的东西吗?好吧,鸭子打字救援!绝对!
tuple((a for a in range(4))) #Output: (0, 1, 2, 3)
我需要多余的括号吗?不!
tuple(a for a in range(4)) #Output: (0, 1, 2, 3)
tuple(a*a for a in range(4)) #Output: (0, 1, 4, 9)
现在,这会产生什么? (x, x*x) for x in [1, 2, 3]
好吧,它是一个表达式,但让我们了解一下它在列表推导中的外观
[(x, x*x) for x in [1, 2, 3]] #Output: [(1, 1), (2, 4), (3, 9)]
啊,它的元组列表?发电机可以做到吗?
my_generator = ((x, x*x) for x in [1, 2, 3]) #<generator object <genexpr> at 0x000000FA4FD2DCA8>
next(my_generator) #Output: (1, 1)
next(my_generator) #Output: (2, 4)
next(my_generator) #Output: (3, 9)
next(my_generator) #Raises StopIteration
是的,看起来不错。因此,它是一个生成器,但它是可迭代的。反正像鸭子一样,不是吗?因此,元组构造函数应该可以正常工作!
tuple((x, x*x) for x in [1, 2, 3]) #Output: ((1, 1), (2, 4), (3, 9))
因此,这一切都包含在内。括号并不总是表示元组,()并非为元组保留。我们在这里看到它们也可以用于生成器表达式!同样,{}不必总是与字典绑定,实际上字典也存在类似于列表理解的东西! (称为dict comprehension)
我强烈建议您浏览链接,以更全面地解释在此一起工作的各个部分。希望这会有所帮助!