用于元组理解和元组创建的Tuple()vs()。

时间:2018-12-22 15:22:40

标签: python tuples

我了解可以通过以下两种方法创建元组:

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}}关系是否不同?

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个分别创建列表或生成器表达式的内衬。稍后,更多关于生成器的知识,足以了解列表理解的工作原理。

list comprehension

的简单示例
[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

我强烈建议您浏览链接,以更全面地解释在此一起工作的各个部分。希望这会有所帮助!