回答
後者。這只是一條線,你很快就會看到它在做什麼。除此之外,只有一個訪問T
可能會更快一點。
後者。這個名字只能綁定一次,而不是發生n + 1次。
哪個變量? – 2011-04-16 00:02:35
蓄電池。 – 2011-04-16 00:02:54
@neil我相信它的「T」只會被綁定一次。 – 2011-04-16 00:04:10
爲了澄清我對伊格納西奧的回答關於增強作業評論總是重新綁定的名稱,即使是可變對象,我提供了下面的例子:正如我在我的評論說
class Broken(list):
def __iadd__(self, other):
list.__iadd__(self, other) # This is not quite right
a = b = Broken()
a += [123]
print(b) # OK
print(a) # What!?
,增強分配實際上擴展到對於可變對象,相當於a = a.__iadd__([123])
。證明這一點的其他經典方法是使用元組:
>>> t = [],
>>> t[0] += [123]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> t[0]
[123]
在上面的例子Broken
該bug是不從__iadd__
方法返回一個值。它應以return self
結尾,否則只需將調用結果返回給父類方法即可。
class Correct(list):
def __iadd__(self, other):
list.__iadd__(self, other)
return self
class AlsoCorrect(list):
def __iadd__(self, other):
return list.__iadd__(self, other)
「Broken」並不完全像列表那樣行事,這是非常令人驚訝的。有沒有辦法讓它重載'__iadd__',同時避免重新綁定? – 2011-04-18 05:35:43
另外,什麼是Python的這種令人驚訝的行爲的理由? – 2011-04-18 05:36:36
+1爲這penatrating知識和罰款演示代碼 – eyquem 2011-04-18 17:26:28
ncoghlan是正確的:在更嚴格的意義上說,增強assignement始終重新綁定的名稱或暗示的項目。但是,由於他的帖子很橢圓,我會嘗試給出更多的基本解釋。
。
在DOC:
object.__iadd__(self, other)
object.__isub__(self, other)
等等
這些方法稱爲實施 增強算術作業 (+ =, - =等等......)。這些方法應該 嘗試做了手術就地 (修改個體經營)和返回結果 (可以是,但不必 是個體經營)。 (....)
例如,爲了 執行該語句
x += y
,其中x
是 ,其具有__iadd__()
方法,x.__iadd__(y
一個類的一個實例)被調用。http://docs.python.org/reference/datamodel.html#object。__add__
我明白這一點如下:
如果x
是具有方法__iadd__()
的實例中,指令x += y
觸發像,該方法的調用:x.__iadd__(y)
其執行,據我所知,如x = __iadd__(x,y)
也就是說:__iadd__()
是兩個參數的函數(參見http://docs.python.org/tutorial/classes.html#method-objects),並且由於每個函數__iadd__(x,y)
都返回分配給x
的內容。這東西是對象x
就地修改,與內存中的相同的地址,如果就地操作是可能的;否則它是另一個對象,另一個地址返回並被賦值爲x
。
所以,嚴格來說,科格倫是正確的:總是進行重新綁定標識符x
的操作,即使__iadd__()
已執行和就地修改的同一對象已經由函數返回__iadd__()
。當我寫«同一個對象»,這意味着«在同一地址»。在這種情況下,Python所做的工作是無用的,它不會改變標識符x
指向的地址,但Python無論如何都不會。
重新綁定到相同的對象改性就地由於x += y
在正常情況下,當x
有一個方法__iadd__()
,是如下的結果的原因是:
a = b = []
print 'b ==',b,' id(b) ==',id(b)
print 'a ==',a,' id(a) ==',id(a)
a += [123]
print '\nb ==',b,' id(b) ==',id(b) # OK
print 'a ==',a,' id(a) ==',id(a)
給出
b == [] id(b) == 18691096
a == [] id(a) == 18691096
b == [123] id(b) == 18691096
a == [123] id(a) == 18691096
說這個a
在這個例子中沒有被重新綁定只有在結果出現的水平才具有某種意義,條件是「重新綁定」的意思是「重新綁定到另一個對象的另一個對象」,這並不是嚴格的意義。實際上,在具體操作層面,重新綁定被有效處理。
。
在以下爲例:
class Broken(list):
def __iadd__(self, other):
list.__iadd__(self, other)
a = b = Broken()
print 'b ==',b,' id(b) ==',id(b)
print 'a ==',a,' id(a) ==',id(a)
a += [123]
print '\nb ==',b,' id(b) ==',id(b) # OK
print 'a ==',a,' id(a) ==',id(a) # What!?
,讓
b == [] id(b) == 18711152
a == [] id(a) == 18711152
b == [123] id(b) == 18711152
a == None id(a) == 505338052
的Broken
的方法__iadd__()
是不規則的,因爲在它的代碼中沒有return
聲明。順便說一句,這就是爲什麼coghlan將它命名爲Broken
。
正在發生的事情是這樣的:
指令
a += [123]
觸發a.__iadd__([123])
執行,因此是真正執行什麼的a = Broken.__iadd__(a,[123])
執行是那麼
list.__iadd__(a,[123])
返回到Broken.__iadd__()
塊該對象修改了in_place。 BUT該精確對象不被Broken.__iadd__()
返回,SO這後者的功能通過返回None
結束。這樣的
Broken.__iadd__(a,[123])
結果是None
,這None
被處理到a
最初指向對象,以及其中b
仍然指向期間分配給a
反正,已被修改到位。
即在已經完全沒有被rebinded標識符
b
結束,指向在所述存儲器中的相同位置修改的對象,並且在已經完全rebinded別處的標識符a
。
。
這段代碼沒問題:它保留了功能list.__iadd__()
所執行的操作,並且它通過a
的方法__iadd__()
湮滅了其結果的分配。顯示這種湮滅的後果與a += [123]
的結果不同,這證明這種分配確實存在。
class UnBroken(list):
def __iadd__(self, other):
return list.__iadd__(self, other)
a = b = UnBroken()
print 'b ==',b,' id(b) ==',id(b)
print 'a ==',a,' id(a) ==',id(a)
a += [123]
print '\nb ==',b,' id(b) ==',id(b) # OK
print 'a ==',a,' id(a) ==',id(a) # OK
給
b == [] id(b) == 18711200
a == [] id(a) == 18711200
b == [123] id(b) == 18711200
a == [123] id(a) == 18711200
:此證明的事實,恢復return語句恢復正常的行爲確認。
wmwmwmwmwmwmwmwmwmwmwmwmwmwmwmwmwmwm
。
下面的代碼片段:
t = ([],)
t[0] += [145]
結果
TypeError: 'tuple' object does not support item assignment
但是,這個錯誤是由於這樣的事實,一個元組的元素的值不能改變或一個事實,即元組拒絕分配的過程?
的第二個原因是正確的,因爲下面的代碼證明了一個元組的值可以改變:
t = ([],)
print 't before ==',t,' id(t) ==',id(t)
el = t[0]
el += [608]
print 't after ==',t,' id(t) ==',id(t)
,給出了一個不同的值,以相同的對象(在同一地點):
t before == ([],) id(t) == 11891216
t after == ([608],) id(t) == 11891216
的原因是,雖然元組是不可變的,它的價值可以改變:
的immuta的價值如果 後者的值發生更改,則包含對可變對象的引用的對象可以更改;然而 容器仍然被認爲是 不可變的,因爲它包含的對象集合 無法更改。 所以,不變性不是嚴格的 相同有一個不可改變的價值, 它更加微妙。一個對象的 可變性由它的類型
http://docs.python.org/reference/datamodel.html#objects-values-and-types
確定。
這微妙允許編寫更好的指出代碼是怎麼回事下:
t = ([],)
print 't before ==',t,' id(t) ==',id(t)
print 't[0] ==',t[0],' id(t[0]) ==',id(t[0])
try:
t[0] += [4744]
except TypeError:
print 't after ==',t,' id(t) ==',id(t)
print 't[0] ==',t[0],' id(t[0]) ==',id(t[0])
t[0] += [8000]
結果
t before == ([],) id(t) == 18707856
t[0] == [] id(t[0]) == 18720608
t after == ([4744],) id(t) == 18707856
t[0] == [4744] id(t[0]) == 18720608
Traceback (most recent call last):
File "I:\what.py", line 64, in <module>
t[0] += [8000]
TypeError: 'tuple' object does not support item assignment
行爲是使用類似於第一個片段的行爲壞了():
指令
t[0] += [4744]
觸發t[0]
「s法__iadd__()
執行以下動作t[0] .__iadd__([4744])
t[0]
是一個列表,該執行是具體t[0] = list.__iadd__(t[0] ,[4744])
所以,通過
t[0]
引用的列表就地被第一修改和然後,試圖使分配完成
此嘗試不是試圖將名稱綁定到就地修改的對象(在那裏我沒有暗示的名字);它試圖將一個項目(一個複合對象中的一個位置)綁定到一個對象,也就是說在這裏把就地修改對象的地址放在一個名爲
t[0]
的位置:複合對象的元素在對其他對象的事實的參考,也就是說這些其他對象,但把地址在該位置
t[0]
之前地址,解釋驗證的t
類型允許此操作:這是我的理解看到的句子以上:«物體的可變性由其類型»確定。此時,解釋器檢測到不允許執行該操作並且產生TypeError
。在我的代碼中,這個錯誤被
try-except
攔截,這個技巧允許在除了部分看到由t[0]
引用的對象確實已被修改。
。
因此,在Broken()
的摘錄中採用了類似的方法:將對就地修改的觀察與對分配的觀察分開。
不同之處在於,這裏的分配是通過其行爲的後果來證明的,而不是其缺席的結果。
。
wmwmwmwmwmwmwmwm
整蠱片段,我覺得。我很難理解這些基礎機制。
謝謝。這回答我的問題ncoghlan。 – 2011-04-18 17:49:00
- 1. Python風格問題
- 2. 風格問題
- 3. Python的風格問題,函數參數
- 4. 背景問題與風格和主題
- 5. PHP風格問題
- 6. 的風格問題
- 7. OOP風格問題
- 8. $ img_attributes風格問題
- 9. PHPExcel風格問題
- 10. Winform風格問題:Windows經典風格?
- 11. DataBinding和風格的問題[WP7]
- 12. WPF DataGrid行和列的風格問題
- 13. OO風格 - 簡單問題
- 14. 風格TargetType屬性問題
- 15. backBarButtonItem(leftbackButtonItem)風格問題
- 16. IE中的風格問題
- 17. Joomla MorfeoShow Fancybox風格問題
- 18. 編碼風格有問題
- 19. 問題TinyMCE的風格
- 20. MVC部署風格問題
- 21. jQuery手風琴風格常見問題解答+和 -
- 22. 主題和風格建議
- 23. Python風格問題:支持類作爲內部類嗎?
- 24. python POST請求問題
- 25. python數組問題,求助!
- 26. Gnuplot求和問題
- 27. python屬性風格
- 28. 崩潰後的IntelliJ風格問題
- 29. 特定的C編程風格問題?
- 30. 計劃編碼風格問題
在CPython上,您還可以將循環移動到C代碼中,這使得代碼更快*。 – ncoghlan 2011-04-17 14:47:40