解释这个列表在一般情况下的理解奇怪和它的用例是什么?

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)

Mar*_*ers 5

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以及生成器表达式都在一个单独的范围内执行.