您好,登錄后才能下訂單哦!
Python 表達式i += x與i = i + x等價嗎?如果你的回答是yes,那么恭喜你正確了50%,為什么說只對了一半呢? 按照我們的一般理解它們倆是等價的,整數操作時兩者沒什么異同,但是對于列表操作,是不是也一樣呢?先看下面兩段代碼:
代碼1
代碼2
代碼1與代碼2中的l2的值是一樣的,但是l1的值卻不一樣,說明i += x與i = i + x是不等價的,那什么情況下等價,什么情況下不等價呢?
弄清楚這個問題之前,首選得明白兩個概念:可變對象與不可變對象。
在 Python 中任何對象都有的三個通用屬性:唯一標識、類型、值。
唯一標識:用于標識對象的在內存中唯一性,它在對象創建之后就不會再改變,函數id()可以查看對象的唯一標識
類型:決定了該對象支持哪些操作,不同類型的對象支持的操作就不一樣,比如列表可以有length屬性,而整數沒有。同樣地對象的類型一旦確定了就不會再變,函數type()可以返回對象的類型信息。
對象的值與唯一標識不一樣,并不是所有的對象的值都是一成不變的,有些對象的值可以通過某些操作發生改變,值可以變化的對象稱之為可變對象(mutable),值不能改變的對象稱之為不可變對象(immutable)
不可變對象(immutable)
對于不可變對象,值永遠是剛開始創建時候的值,對該對象做的任何操作都會導致一個新的對象的創建。
整數 “1” 是一個不可變對象,最初賦值的時候,a指向的是整數對象 1 ,但對變量a執行+=操作后, a 指向另外一個整數對象 2 ,但對象 1 還是在那里沒有發生任何變化,而 變量 a 已經指向了一個新的對象2。常見的不可變對象有:int、tuple、set、str。
可變對象(mutable)
可變對象的值可以通過某些操作動態的改變,比如列表對象,可以通過append方法不斷地往列表中添加元素,該列表的值就在不斷的處于變化中,一個可變對象賦值給兩個變量時,他們共享同一個實例對象,指向相同的內存地址,對其中任何一個變量操作時,同時也會影響另外一個變量。
執行append操作后,對象的內存地址不會改變,x、y 依然指向的是原來同一個對象,只不過是他的值發生了變化而已。
理解完可變對象與不可變對象后,回到問題本身,+=與+的區別在哪里呢?
+= 操作首先會嘗試調用對象的 __iadd__方法,如果沒有該方法,那么嘗試調用__add__方法,先來看看這兩個方法有什么區別
__add__和__iadd__的區別
__add__ 方法接收兩個參數,返回它們的和,兩個參數的值均不會改變。
__iadd__ 方法同樣接收兩個參數,但它是屬于 in-place 操作,就是說它會改變第一個參數的值,因為這需要對象是可變的,所以對于不可變對象沒有__iadd__方法。
顯然,整數對象是沒有__iadd__的,而列表對象提供了__iadd__方法。
>>> l2 += [3]#代碼1:使用__iadd__,l2的值原地修改
代碼1中的 += 操作調用的是__iadd__方法,他會原地修改l2指向的那個對象本身的值
>>> l2 = l2 + [3]# 代碼2:調用 __add__,創建了一個新的列表,賦值給了l2
而代碼2中的 + 操作調用的是 __add__方法,該方法會返回一個新的對象,原來的對象保持不變,l1還是指向原來的對象,而l2已經指向一個新的對象。
以上就是表達式 i += x 與 i = i + x 的區別。因此對于列表進行 += 操作時,會存在潛在的bug,因為l1會因為l2的變化而發生改變,就像函數的參數不宜使用可變對象作為關鍵字參數一樣。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。