2011-10-12 44 views
2

在Python,如果定義三個類:底層機制Python類成員查找

class A: 
    name = 'oliver' 
    hailstone_ending = [4,2,1] 

class B: 
    def __init__(self): 
     self.name = 'oliver' 
     self.hailstone_ending = [4,2,1] 

class C: 
    pass 

c = C() 
c.name = 'oliver' 
c.hailstone_ending = [4,2,1] 

引擎蓋下,確實成員查找功能中用於每個類別的相同的方式?看起來A只需要在字典上查找所有實例的成員;另一方面,另一方面,需要使用存儲在這些實例中的每一箇中的字典。如果口譯人員非常聰明,理論上可以注意到B必須包括namehailstone_ending;因此,它可能相當於A

但另一方面,如果del操作在查找類成員的字典上被允許,所有這些類中的查找機制可能是等價的,因爲可用成員將依賴於實例。

我的興趣是我有一些代碼創建了幾千個類型爲C的類,我注意到它很慢並且內存很餓。我最近以不同的方式重寫了它,感覺效率更高(但我沒有嚴格測試它,所以它可能是相同的)。

非常感謝您的洞察力!

+0

不...... A''與'B'非常不同。口譯員很聰明,可以注意到這一點。 – JBernardo

回答

2

在引擎蓋下,每個類都以同樣的方式執行成員查找功能嗎?

除非您重寫__getattribute__,否則屬性查找將首先檢查對象屬性,然後鍵入屬性。它並不關心這個班是怎麼來的。

看來A只會在字典上查找所有實例的成員;另一方面,C需要使用存儲在這些實例中的字典。如果口譯員非常聰明,理論上可以注意到B的所有實例都必須包含成員名稱和hailstone_ending;因此,它可能等於A.

A中,屬性存儲在A.__dict__中,即在類型上。在BC中,屬性存儲在self.__dict__中,即在實例上。兩種字典都存在於所有情況下。沒有什麼更多。不,BC之間沒有區別。

+0

一個調整:'del'屬性查找:它必須找到屬性才能刪除它。記住:它實際上是從某個名稱空間中刪除一個屬性,所以它需要執行查找。它沒有傳遞一個屬性查找結果的值,因爲它會丟失關於屬性來自哪裏的信息。 –

2

在python中,每個類和每個實例都獲取一個字典。 A使用類字典。類BC的示例正在使用實例字典。 B將不等於A - python不打算很快,如果不是不可能證明B沒有實例會發生變異將是非常困難的。

證明:

>>> class D: 
... def __init__(self): 
...  self.a = 3 
... 
>>> d = D() 
>>> d.a 
3 
>>> D.a 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: class D has no attribute 'a' 
>>> dd = D() 
>>> dd.a 
3 
>>> D.a 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: class D has no attribute 'a' 

你的問題讓我覺得JavaScript的原型。

此外:如果在實例字典中找不到成員,但寫入將使用實例字典,則成員查找可以返回到類字典中。

+0

我知道Python的速度並不快 - 我被告知了很多。想知道這些事情只是在化妝。我學會了使用TI-85圖形計算器進行編程,有時學習如何從小的隱藏位置擠出速度很有趣。如果你遇到一些只是*看起來不可能變得更快的東西,它會非常有用! – user