Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么在for循环中允许使用列表订阅?_Python_For Loop_Syntax - Fatal编程技术网

Python 为什么在for循环中允许使用列表订阅?

Python 为什么在for循环中允许使用列表订阅?,python,for-loop,syntax,Python,For Loop,Syntax,Python如何接受以下构造: l = [1, 2, 3, 4] for i, l[i] in enumerate(l[:]): print(l[i]) 似乎没有抱怨,它愉快地打印出1234。这是如何允许的以及它的具体作用是什么?允许迭代变量为目标列表中指定的任何变量: for_stmt ::= "for" target_list "in" expression_list ":" suite ["else" ":" suite] 其中,对于以下构造: t

Python如何接受以下构造:

l = [1, 2, 3, 4]
for i, l[i] in enumerate(l[:]):
    print(l[i])
似乎没有抱怨,它愉快地打印出
1234
。这是如何允许的以及它的具体作用是什么?

允许迭代变量为
目标列表中指定的任何变量:

for_stmt ::=  "for" target_list "in" expression_list ":" suite
              ["else" ":" suite]
其中,对于以下构造:

target_list     ::=  target ("," target)* [","]
target          ::=  identifier
                     | "(" [target_list] ")"
                     | "[" [target_list] "]"
                     | attributeref
                     | subscription
                     | slicing
                     | "*" target
这意味着您还可以执行其他古怪的操作,如分配给切片:

for l[::-1] in [l, l, l]: pass  
或订阅:

class Foo: a = 20
for Foo.a in range(2): pass
但我真的不知道你为什么要这么做

这是循环
s的副产品,基本上为每次迭代执行赋值语句,如参考文献中所述:

使用标准分配规则(请参见分配语句)将每个项目依次分配到目标列表,然后执行套件

因此,循环所做的是,它从
表达式列表
中获取迭代器,并对
目标列表
中的每个值执行赋值。本质上等同于以下
while
循环:

it = enumerate(l[:])
while True:
    try:
        i, l[i] = next(it)
        print(l[i])
    except StopIteration:
        break 
dis
还可以在字节码级别显示此行为。使用稍微简化的版本:

def _():
    for i, l[i] in enumerate(l[:]):
        pass
您将获得以下输出:

dis(_)
  2           0 SETUP_LOOP              40 (to 43)
              3 LOAD_GLOBAL              0 (enumerate)
              6 LOAD_GLOBAL              1 (l)
              9 LOAD_CONST               0 (None)
             12 LOAD_CONST               0 (None)
             15 BUILD_SLICE              2
             18 BINARY_SUBSCR
             19 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             22 GET_ITER
        >>   23 FOR_ITER                16 (to 42)
             26 UNPACK_SEQUENCE          2
             29 STORE_FAST               0 (i)
             32 LOAD_GLOBAL              1 (l)
             35 LOAD_FAST                0 (i)
             38 STORE_SUBSCR

  3          39 JUMP_ABSOLUTE           23
        >>   42 POP_BLOCK
        >>   43 LOAD_CONST               0 (None)
             46 RETURN_VALUE
如果相关赋值是在命令的
FOR\u ITER
之后执行的:

             26 UNPACK_SEQUENCE          2
             29 STORE_FAST               0 (i)
             32 LOAD_GLOBAL              1 (l)
             35 LOAD_FAST                0 (i)
             38 STORE_SUBSCR
解压缩序列并将其分配给
i
l[i]


如果你也反汇编
dis('i,l[i]=(1,2)
,你会发现如果你忽略元组
(1,2)
的初始加载和值的返回,操作是完全相同的。

@johnsharpe你到底是怎么找到它的?我找了整整20分钟,但什么也找不到!:-)我在谷歌上搜索了“for loop目标列表中的python订阅”,这是第六次点击。我当然错过了。啊,好吧,又是一个路标!这里的问题不就是解释赋值的顺序以及绑定创建的顺序吗?这使得while示例本身不具有解释性?@pvg否否我试图强调的问题是,有一个赋值正在进行,因此
target\u列表中的任何内容都可以作为
for循环的迭代变量。编写
while
是为了显示执行的命令序列的友好形式,以及它如何包含隐藏的赋值。啊,你说得对,我明白你的意思。很明显,我患有python绑定和作用域斯德哥尔摩综合症。@pvg-hah,那么您可以检查一下,这很好地解释了
for循环
s:-)中的作用域情况