2012-07-20 54 views
10

在「Python的重要參考,」由大衛比茲利的第35頁,他首先指出:是否分配另一個變量爲一個字符串進行復印或增加引用計數

對於不可改變的數據,比如字符串,則口譯員積極地在程序的不同部分之間共享對象 。

不過,後來在同一頁面上,他說

對於不可改變的對象,如數字和字符串,該分配 有效地創建一個副本。

但這不是矛盾嗎?一方面他說他們是共享的,但他說他們被複制。

回答

5

有效創建副本。它不是實際上是創建一個副本。具有兩個副本並且有兩個名稱共享相同值的主要區別在於,在後一種情況下,通過一個名稱進行修改會影響其他名稱的值。如果該值不能被突變,則這種差異會消失,因此對於不可變對象,值是否被複制幾乎沒有實際的結果。

有些情況下,即使對於不可變類型(例如,通過使用id函數或is運算符),您仍可以區分副本和不同對象(但使用Python內置不可變類型(例如字符串和數字)。

+1

這有很多實際的結果。考慮一下常用的'if變量是無'成語('None'是內置的不可變python對象,如果對象爲None或者看起來像'None'則很重要。原則上你可以用一個字符串來做同樣的事情,這個字符串是特殊的。 – mgilson 2012-07-20 20:06:22

+0

如果使用'if x is None'而不是'if x == None',實際上會有很少的實際後果。它們只會在奇怪的角落情況下有所不同(例如,'x'是定義奇怪'__eq__'測試的對象)。在字符串和數字上使用'is'更加實際。不推薦依賴'is'作爲特殊的「預留」字符串/整數,因爲這個「預留」取決於實現。 – BrenBarn 2012-07-20 20:08:45

+1

考慮一下使用'if x is None:'來檢查是否收到關鍵字參數的常見情況。如果你想接受None作爲一個值怎麼辦?你可以做'SENTINAL =''; def foo(arg = SENTINAL);如果(arg是SENTINAL):arg = []'例如。這不是實現相關的。 – mgilson 2012-07-20 20:12:27

9

python中的賦值永遠不會創建副本(只有在例如使用__setattr__屬性或描述符重新定義類成員的賦值時,纔可能創建副本)。

a = foo() 
b = a 

無論是從foo回來還沒有被複制打完,而是你有兩個變量ab指向同一個對象。無論對象是不可變的還是不可變的。

有了不可改變的對象但是它很難說,如果是這樣的話(因爲你不能用一個變量發生變異的對象和檢查的變化是使用其他可見的),所以你可以自由地認爲確實ab不能相互影響。

對於一些不可變對象也Python是免費重用舊的對象,而不是創造新的後

a = x + y 
b = x + y 

其中兩個xy是數字(如此之和是一個數字,是不可改變的)可能是ab將指向相同的對象。請注意,沒有這樣的保證......也可能是它們會指向具有相同值的不同對象。

重要的是要記住的是,除非特別指示使用例如Python,否則Python永遠不會複製副本。 copydeepcopy。這是重要的可變對象,以避免意外。你可以看到

一個常見的成語是例如:

class Polygon: 
    def __init__(self, pts): 
     self.pts = pts[:] 
    ... 

在這種情況下self.pts = pts[:]代替self.pts = pts做出點的整個陣列的複製,以確保點列表將不會改變意外的是,如果在創建對象後將更改應用於傳遞給構造函數的列表。

+0

我喜歡這個回答(+1) – mgilson 2012-07-20 20:04:21

相關問題