首页 > 解决方案 > Python打印函数不返回更新的变量

问题描述

我正在学习 Python 和一些相关的东西让我很print困惑。不确定是否有人已经问过同样的问题:

>>> x = 1
>>> x, y = x + 2, print(x)
1

我知道输出是 Python函数1的副作用。print但是为什么不打印3呢?我期待3因为x在第二行更新?我在想它相当于(显然是错误的):

>>> x = 1
>>> x = x + 2
>>> x
3
>>> y = print(x)
3

我想了解这个print函数背后的逻辑。为什么它不打印更新的x值?

我是编程世界的新手,因此非常感谢任何见解!

标签: pythonprintingassign

解决方案


首先评估右侧的所有内容。您可以使用 python 字节码反汇编程序来查看发生了什么:

>>> import dis
>>> dis.dis('x, y = x + 2, print(x)')
  1           0 LOAD_NAME                0 (x)
              2 LOAD_CONST               0 (2)
              4 BINARY_ADD
              6 LOAD_NAME                1 (print)
              8 LOAD_NAME                0 (x)
             10 CALL_FUNCTION            1
             12 ROT_TWO
             14 STORE_NAME               0 (x)
             16 STORE_NAME               2 (y)
             18 LOAD_CONST               1 (None)
             20 RETURN_VALUE
>>>

注意,x + 2和被首先print(x)评估。BINARY_ADD 和 CALL_FUNCTION 出现在两个s 之前。STORE_NAME

注意,你可以认为这相当于先构建一个元组,

temp = (x + 2, print(x))

然后简单地说:

x, y = temp

但是,请注意,根据反汇编程序,不会创建实际的中间元组。调用堆栈用于存储中间值。这是编译器优化。但是,优化不适用于长度大于 3 的元组,因此使用 4,您会看到创建了一个中间元组:

>>> dis.dis('foo, bar, baz, bang  = bang, baz, bar, foo')
  1           0 LOAD_NAME                0 (bang)
              2 LOAD_NAME                1 (baz)
              4 LOAD_NAME                2 (bar)
              6 LOAD_NAME                3 (foo)
              8 BUILD_TUPLE              4
             10 UNPACK_SEQUENCE          4
             12 STORE_NAME               3 (foo)
             14 STORE_NAME               2 (bar)
             16 STORE_NAME               1 (baz)
             18 STORE_NAME               0 (bang)
             20 LOAD_CONST               0 (None)
             22 RETURN_VALUE
>>>

注意BUILD_TUPLEand UNPACK_SEQUENCE,这是在 Python 中解包的一般方式。只是编译器使用 ROT_TWO 和 ROT_THREE 操作码优化了二或三的常见情况。

注意,由于右手边是先评估的,这使得 Python 交换习语可以工作!

x, y = y, x

如果这相当于:

x = y
y = x

你会失去 x 的价值而不是交换!


推荐阅读