fre*_*gnu 0 python language-features list-comprehension
是的.这发生了.当我心不在焉地把一个索引放在变量中时.解释(它?).在一般情况下发生了什么以及它的用例是什么?
>>> [q for q[0] in [range(10),range(10,-1,-1)]]
Traceback (most recent call last):
File "<pyshell#209>", line 1, in <module>
[q for q[0] in [range(10),range(10,-1,-1)]]
NameError: name 'q' is not defined
>>> [q for q in [range(10),range(10,-1,-1)]]
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]
>>> [q for q[0] in [range(10),range(10,-1,-1)]]
[[[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]
>>> [q for q[0] in [range(10),range(10,-1,-1)]]
[[[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]
>>> [q for q[0] in [range(10,-1,-1),range(10)]]
[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]
>>> [q for q[0] in [range(10),range(10,-1,-1)]]
[[[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]
>>> [q for q[0] in [range(10,-1,-1),range(10)]]
[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]
>>> [q for q[0] in [range(10),range(10,-1,-1)]]
[[[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]
>>> [q for q[0] in [range(10),range(10,-1,-1)]]
[[[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]
>>> [q for q in [range(10),range(10,-1,-1)]]
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]
Run Code Online (Sandbox Code Playgroud)
该for循环复合语句重用的target_list结构中也使用分配:
for_stmt ::= "for" target_list "in" expression_list ":" suite
Run Code Online (Sandbox Code Playgroud)
这是因为对于循环的每次迭代,"当前"值被分配给目标列表.这也意味着您可以分配给项目.引用文档:
依次使用标准的分配规则将每个项目分配到目标列表,
在Python中,这是完全正常的:
q = [None]
q[0] = 'foobar'
Run Code Online (Sandbox Code Playgroud)
如果名称存在并支持项目分配,您可以在for循环中执行相同操作.这就是你的第一次尝试失败的原因:q
>>> [q for q[0] in [range(10),range(10,-1,-1)]]
Traceback (most recent call last):
File "<pyshell#209>", line 1, in <module>
[q for q[0] in [range(10),range(10,-1,-1)]]
NameError: name 'q' is not defined
Run Code Online (Sandbox Code Playgroud)
还没有名字q,所以分配q[0]失败.
在for循环中使用它可能没有真正的用例,但target_list这里重用的优点是它使语法和解析器更简单,并允许你使用赋值解包,例如赋值给多个目标:
for key, value in mapping.items():
# unpack two-value tuples returned by .items() into two names
Run Code Online (Sandbox Code Playgroud)
接下来,您执行了一个直接列表理解:
>>> [q for q in [range(10),range(10,-1,-1)]]
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]
Run Code Online (Sandbox Code Playgroud)
在Python 2中,列表解析的本地名称泄漏 ; 它们位于列表理解定义的范围内.即使在理解范围之后,也可以查看Python列表理解重新绑定名称.这是正确的吗?
因此,在执行上面的列表理解的那一刻,名称q存在,仍然绑定到最后一次迭代的值:
>>> q
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Run Code Online (Sandbox Code Playgroud)
这是一个列表对象,因此它支持项目分配.从那里出来,你要做的就是项目分配q[0]和重新引用此一个全局q名称:
>>> [q for q[0] in [range(10),range(10,-1,-1)]]
[[[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]
>>> q
[[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Run Code Online (Sandbox Code Playgroud)
您已将两个range()生成的列表中的每一个放在索引0中q,但在完成列表推导之后,q[0]将绑定到迭代的最后一个列表.
在Python 3中,for循环中的项目赋值仍然有效,但是列表推导不再"泄漏"本地名称,因为它们在单独的范围内执行.无论Python版本如何,Dict和set comprehensions以及生成器表达式都在一个单独的范围内执行.