看起来e for e in [1, 2, 3, 4, 5]
是生成器表达式,(e for e in [1, 2, 3, 4, 5])
被计算为生成器对象。因此,我认为(...)
是Python中的评估。
我假设list(e for e in [1, 2, 3, 4, 5])
告诉Python运行时评估可迭代表达式,生成其对象,并调用list
函数来调用yield
,直到它用完元素为止。
print(list(e for e in [1, 2, 3, 4, 5]))
---
[1, 2, 3, 4, 5]
问题
以下代码中的[...]
究竟是什么?它的机制是什么?[ e for e in [1, 2, 3, 4, 5] ]
生成一个列表对象,因此我认为它是对e for e in [1, 2, 3, 4, 5]
进行评估以创建生成器对象和调用生成器对象的组合。它是对list(...)
的函数调用的别名吗?
print([ e for e in [1, 2, 3, 4, 5] ])
---
[1, 2, 3, 4, 5]
对于使用slice对象的列表访问,我假设[1:3]
是在告诉Python评估1:3
表达式以生成slice对象。
print([1,2,3][1:3])
print([1,2,3][slice(1,3,1)])
---
[2, 3]
[2, 3]
[(1:3)]
失败,因为它试图评估已评估的1:3
?
print([1,2,3][(1:3)])
---
File "<ipython-input-167-c20e211025dc>", line 1
print([1,2,3][(1:3)])
^
SyntaxError: invalid syntax
[1, 2, 3, 4, 5]
是一个列表文字。
CCD_ 16是一个生成器理解。list(value for item in iterable)
将使用生成器调用list()
构造函数,当然生成器只生成一个列表。为了减少歧义,不能赤裸裸地使用生成器理解。但它既可以在一组括号内使用,也可以在另一个表达式内使用,例如函数调用中的参数。类似的限制适用于Python 3.8中添加的:=
(海象(运算符。
CCD_ 20是一种列表理解。请注意,Python将其视为一个完全独立的语法结构。
实现可能大致相同,但据我所知,Python编译器在处理代码时分别检测生成器理解和列表理解,并且列表理解并没有被定义为生成器理解或列表文字的子集/特例。
我确信类似的事情也适用于切片语法——它被定义为自己的语法,特别是在列表索引的上下文中,而不是在其他上下文中。lst[1:3]
编译成lst.__getitem__(slice(1, 3))
是编译过程的一部分,对于语法1:3
来说并不是一件普通的事情(因为这很模糊(。
换句话说,如果我没有记错的话,就Python编译器而言,lst[x:y:z]
与lst[x]
是不同的语法结构。
*本文中的信息基于我对CPython源代码中各种方法的理解和先前的交互。我在语法、编译器和编译的代码之间得出了一些可能无效的结论。