![](/img/trans.png)
[英]How to migrate lambda from python2 to python3 and handle removed tuple parameter unpacking in python3
[英]What is with this change of unpacking behavior from Python2 to Python3
昨天我在Python 2和Python 3之間遇到了這個奇怪的解包差異,並且在快速谷歌搜索之后似乎沒有找到任何解釋。
Python 2.7.8
a = 257
b = 257
a is b # False
a, b = 257, 257
a is b # False
Python 3.4.2
a = 257
b = 257
a is b # False
a, b = 257, 257
a is b # True
我知道它可能不會影響程序的正確性,但它確實讓我有點煩惱。 任何人都可以在拆包時給出一些關於這種差異的見解嗎?
這種行為至少部分與解釋器如何進行常量折疊以及REPL如何執行代碼有關。
首先,請記住CPython首先編譯代碼(到AST然后是字節碼)。 然后它評估字節碼。 在編譯期間,腳本會查找不可變的對象並對其進行緩存。 它還對它們進行重復數據刪除。 如果它看到了
a = 257
b = 257
它會將a和b存儲在同一個對象上:
import dis
def f():
a = 257
b = 257
dis.dis(f)
#>>> 4 0 LOAD_CONST 1 (257)
#>>> 3 STORE_FAST 0 (a)
#>>>
#>>> 5 6 LOAD_CONST 1 (257)
#>>> 9 STORE_FAST 1 (b)
#>>> 12 LOAD_CONST 0 (None)
#>>> 15 RETURN_VALUE
注意LOAD_CONST 1
。 1
是co_consts
的索引:
f.__code__.co_consts
#>>> (None, 257)
所以這些都加載相同的257
。 為什么不出現這種情況:
$ python2
Python 2.7.8 (default, Sep 24 2014, 18:26:21)
>>> a = 257
>>> b = 257
>>> a is b
False
$ python3
Python 3.4.2 (default, Oct 8 2014, 13:44:52)
>>> a = 257
>>> b = 257
>>> a is b
False
?
在這種情況下,每一行都是一個單獨的編譯單元,重復數據刪除不能跨越它們。 它的工作原理類似於
compile a = 257
run a = 257
compile b = 257
run b = 257
compile a is b
run a is b
因此,這些代碼對象都將具有唯一的常量緩存。 這意味着如果我們刪除換行符,則is
將返回True
:
>>> a = 257; b = 257
>>> a is b
True
事實上,這兩個Python版本都是如此。 事實上,這正是原因所在
>>> a, b = 257, 257
>>> a is b
True
也返回True
; 這不是因為解包的任何屬性; 它們只是放在同一個編譯單元中。
對於未正確折疊的版本,返回False
; 電影或鏈接到Ideone ,顯示2.7.3和3.2.3失敗。 在這些版本中,創建的元組不會與其他常量共享其項目:
import dis
def f():
a, b = 257, 257
print(a is b)
print(f.__code__.co_consts)
#>>> (None, 257, (257, 257))
n = f.__code__.co_consts[1]
n1 = f.__code__.co_consts[2][0]
n2 = f.__code__.co_consts[2][1]
print(id(n), id(n1), id(n2))
#>>> (148384292, 148384304, 148384496)
但是,這不是關於如何解開對象的變化; 它只是改變對象在co_consts
中的存儲co_consts
。
我認為這實際上是偶然的,因為我不能用Python 3.2重現這種行為。
這個問題http://bugs.python.org/issue11244引入了一個CONST_STACK
來修復常量元組的問題,其中負數未被優化(查看peephole.c
的補丁,其中包含Python的優化運行)。
這似乎也導致了給定的行為。 還在調查這個:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.