Python 为什么这两个代码给出相同的结果?

Python 为什么这两个代码给出相同的结果?,python,python-3.x,Python,Python 3.x,代码1: 代码2: 两者的结果: 为什么第二个代码中的递增对结果没有影响?从迭代中获得的i值是枚举函数的输出,而不是它的输入 修改它不会影响枚举过程,并且for…in循环将使用枚举生成的内容不断覆盖变量,而不管您在循环体中将其设置为什么 与Java和C不同的是,python中的循环会在上下循环。它们不依赖于计数器。从迭代中获得的i值是枚举函数的输出,而不是它的输入 修改它不会影响枚举过程,并且for…in循环将使用枚举生成的内容不断覆盖变量,而不管您在循环体中将其设置为什么 与Java和C不同的

代码1:

代码2:

两者的结果:

为什么第二个代码中的递增对结果没有影响?

从迭代中获得的i值是枚举函数的输出,而不是它的输入

修改它不会影响枚举过程,并且for…in循环将使用枚举生成的内容不断覆盖变量,而不管您在循环体中将其设置为什么

与Java和C不同的是,python中的循环会在上下循环。它们不依赖于计数器。

从迭代中获得的i值是枚举函数的输出,而不是它的输入

修改它不会影响枚举过程,并且for…in循环将使用枚举生成的内容不断覆盖变量,而不管您在循环体中将其设置为什么


与Java和C不同的是,python中的循环会在上下循环。它们不依赖于计数器。

通过查看CPython在第二个示例中生成的字节码,可以找到一些见解:

>>> from dis import dis                                                                                           
>>> def with_increment(): 
        for i, x in enumerate(data, 1): 
            print(i, x) 
            i += 1                                                                                                              
>>> dis(with_increment)                                                                                           
  2           0 SETUP_LOOP              40 (to 42)
              2 LOAD_GLOBAL              0 (enumerate)
              4 LOAD_GLOBAL              1 (data)
              6 LOAD_CONST               1 (1)
              8 CALL_FUNCTION            2
             10 GET_ITER
        >>   12 FOR_ITER                26 (to 40)
             14 UNPACK_SEQUENCE          2
             16 STORE_FAST               0 (i)
             18 STORE_FAST               1 (x)

  3          20 LOAD_GLOBAL              2 (print)
             22 LOAD_FAST                0 (i)
             24 LOAD_FAST                1 (x)
             26 CALL_FUNCTION            2
             28 POP_TOP

  4          30 LOAD_FAST                0 (i)
             32 LOAD_CONST               1 (1)
             34 INPLACE_ADD
             36 STORE_FAST               0 (i)
             38 JUMP_ABSOLUTE           12
        >>   40 POP_BLOCK
        >>   42 LOAD_CONST               0 (None)
             44 RETURN_VALUE
我们感兴趣的部分是字节12-38,它对应于循环体。每次迭代开始时,按顺序执行以下操作:

UNPACK_SEQUENCE 2-枚举生成的元组的组件被推送到堆栈上

STORE_FAST 0-堆栈顶部的值存储在第一个局部变量i中

STORE_FAST 1-堆栈顶部的值存储在第二个局部变量x中


这里需要注意的关键是,我们从不看i的当前值——每次迭代都会盲目地用迭代器生成的任何内容覆盖它。在上一次迭代中,i中使用的任何对象都被完全遗忘。

通过查看CPython在第二个示例中生成的字节码,可以找到一些见解:

>>> from dis import dis                                                                                           
>>> def with_increment(): 
        for i, x in enumerate(data, 1): 
            print(i, x) 
            i += 1                                                                                                              
>>> dis(with_increment)                                                                                           
  2           0 SETUP_LOOP              40 (to 42)
              2 LOAD_GLOBAL              0 (enumerate)
              4 LOAD_GLOBAL              1 (data)
              6 LOAD_CONST               1 (1)
              8 CALL_FUNCTION            2
             10 GET_ITER
        >>   12 FOR_ITER                26 (to 40)
             14 UNPACK_SEQUENCE          2
             16 STORE_FAST               0 (i)
             18 STORE_FAST               1 (x)

  3          20 LOAD_GLOBAL              2 (print)
             22 LOAD_FAST                0 (i)
             24 LOAD_FAST                1 (x)
             26 CALL_FUNCTION            2
             28 POP_TOP

  4          30 LOAD_FAST                0 (i)
             32 LOAD_CONST               1 (1)
             34 INPLACE_ADD
             36 STORE_FAST               0 (i)
             38 JUMP_ABSOLUTE           12
        >>   40 POP_BLOCK
        >>   42 LOAD_CONST               0 (None)
             44 RETURN_VALUE
我们感兴趣的部分是字节12-38,它对应于循环体。每次迭代开始时,按顺序执行以下操作:

UNPACK_SEQUENCE 2-枚举生成的元组的组件被推送到堆栈上

STORE_FAST 0-堆栈顶部的值存储在第一个局部变量i中

STORE_FAST 1-堆栈顶部的值存储在第二个局部变量x中


这里需要注意的关键是,我们从不看i的当前值——每次迭代都会盲目地用迭代器生成的任何内容覆盖它。在上一次迭代中,i中的任何对象都被完全遗忘。

i的值在每次迭代中都会自动更新。不管您如何更改它,这些更改都会被覆盖。Python for循环用于每个循环,而不是init test increment循环。拧动循环变量不会影响for each循环中的下一个元素。@DYZ我理解,但是使用什么机制来记住I的前一个状态呢?这与python中作用域变量的概念有关吗?请提供预期的输出。关键是在迭代之间我不会被记住。枚举有它自己的内部计数器,它与i分开。i的值在每次迭代时自动更新。不管您如何更改它,这些更改都会被覆盖。Python for循环用于每个循环,而不是init test increment循环。拧动循环变量不会影响for each循环中的下一个元素。@DYZ我理解,但是使用什么机制来记住I的前一个状态呢?这与python中作用域变量的概念有关吗?请提供预期的输出。关键是在迭代之间我不会被记住。enumerate有自己的内部计数器,它与i分开。
1 A
2 B
3 C
4 D
>>> from dis import dis                                                                                           
>>> def with_increment(): 
        for i, x in enumerate(data, 1): 
            print(i, x) 
            i += 1                                                                                                              
>>> dis(with_increment)                                                                                           
  2           0 SETUP_LOOP              40 (to 42)
              2 LOAD_GLOBAL              0 (enumerate)
              4 LOAD_GLOBAL              1 (data)
              6 LOAD_CONST               1 (1)
              8 CALL_FUNCTION            2
             10 GET_ITER
        >>   12 FOR_ITER                26 (to 40)
             14 UNPACK_SEQUENCE          2
             16 STORE_FAST               0 (i)
             18 STORE_FAST               1 (x)

  3          20 LOAD_GLOBAL              2 (print)
             22 LOAD_FAST                0 (i)
             24 LOAD_FAST                1 (x)
             26 CALL_FUNCTION            2
             28 POP_TOP

  4          30 LOAD_FAST                0 (i)
             32 LOAD_CONST               1 (1)
             34 INPLACE_ADD
             36 STORE_FAST               0 (i)
             38 JUMP_ABSOLUTE           12
        >>   40 POP_BLOCK
        >>   42 LOAD_CONST               0 (None)
             44 RETURN_VALUE