我正在学习Python,而与print
相关的东西使我感到困惑。不确定是否有人已经问过相同的问题:
>>> x = 1
>>> x, y = x + 2, print(x)
1
我知道输出1
是Python print
函数的副作用。但是为什么不打印3
?我期待3
是因为x
在第二行中已更新?我以为这等效于(显然是错误的):
>>> x = 1
>>> x = x + 2
>>> x
3
>>> y = print(x)
3
我想了解此print
函数背后的逻辑。为什么不打印更新后的x
值?
我是编程界的新手,所以对任何见解都表示赞赏!
答案 0 :(得分:3)
首先评估右侧的所有内容。您可以使用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)
的评估是 first 。 BINARY_ADD和CALL_FUNCTION发生在两个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_TUPLE
和UNPACK_SEQUENCE
,这是在Python中解压缩的一般方法。只是编译器使用ROT_TWO和ROT_THREE操作码优化了二到三的常见情况。
请注意,由于首先要评估右侧,因此可以使用Python交换习惯用法!
x, y = y, x
如果这等同于:
x = y
y = x
您将失去x的值而不是交换!
答案 1 :(得分:0)
>>> x = 1
>>> x, y = x + 2, print(x)
1
print(x)
输出存储在您分配的x中的值
要打印3,您需要 打印(y)
作为y存储x + 2的值
答案 2 :(得分:0)
因为python逐行处理(意味着在整行之后对其进行处理),所以x
尚未更新,因此这无法按预期运行,但是如果您进行;
(分号)就可以了,因为分号;
基本上也是行的分隔符,因此;
之后的所有内容基本上都被当作新行,演示:
>>> x=1
>>> x, y = x + 2,0; print(x)
3
>>>
问题是y
将为0:
>>> y
0
>>>
因为我这样做,所以您必须有一个值
但是,如果需要的话,将其删除:
>>> x=1
>>> x, y = x + 2,0; print(x)
3
>>> del y
>>> y
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
y
NameError: name 'y' is not defined
>>>
答案 3 :(得分:0)
在处理完右侧的所有内容之前,赋值左侧的值不会更新。这就是为什么当您尝试在右侧打印时X尚未为3的原因。