2016-07-31 45 views
0

根據Python的2.7.12文檔:爲什麼只在新樣式類中偏愛object .__ setattr __(self,name,value)?

如果__setattr__()想分配給一個實例屬性,它應該 不能簡單地執行self.name = value - 這會導致遞歸調用 本身。相反,它應該將值插入實例屬性的詞典 中,例如self.__dict__[name] = value對於 新樣式類,而不是訪問實例字典,它應該調用具有相同名稱的基類方法,例如, object.__setattr__(self, name, value)

但是,下面的代碼工作正如人們所預料:

class Class(object): 
    def __setattr__(self, name, val): 
     self.__dict__[name] = val; 

c = Class() 
c.val = 42 
print c.val 

我知道super(Class, obj).__setattr__(name, value)可以確保所有基類的__setattr__方法被調用,但經典的類還可以從基礎類繼承。那麼爲什麼只推薦新的風格類?

或者,另一方面,爲什麼不推薦經典課程?

+1

*那麼爲什麼只推薦用於新樣式類?*調用'__setattr__'而不是直接在實例字典上操作允許超類對發生的事情進行「監督」。將這種方法看作是新風格類別的優勢。它可能會被推薦用於所有類,但不能繼承*的舊式類沒有可調用'__setattr__'方法的超類。 – jedwards

+1

@jedwards是的,因爲經典類沒有'classobj .__ setattr__',只有'object .__ setattr__'用於新樣式類。 –

+0

你完全正確。我想說的是,我認爲你把加粗的那句話,沒有這麼多來自字典,直接使用實例挫折(如你表明,它工作在很多情況下完全正常,並作爲馬亭顯示,存在這樣的情況也不會),但更多的鼓勵*使用'__setattr__',這允許超類有些監督和使用諸如描述符之類的新特徵。對不起,如果我不清楚:) – jedwards

回答

3

新樣式類可以使用,此時不存在要指定的__dict__。新樣式類別還支持其他數據描述符,該類定義在處理某些名稱的屬性設置或刪除的類上。

documentation on slots

默認情況下,新老風格的類的實例有一個字典屬性存儲。這浪費了具有很少實例變量的對象的空間。創建大量實例時,空間消耗可能會變得尖銳。

默認值可以通過在新樣式類定義中定義__slots__來覆蓋。聲明__slots__需要一系列實例變量,並在每個實例中保留足夠的空間以保存每個變量的值。因爲不爲每個實例創建__dict__,所以節省空間。

通過在類上添加data descriptors來實現對插槽的訪問;對於每個這樣的屬性具有__set__和/或__del__方法的對象。

數據描述符的另一個例子是property() objects,它附加了一個setter或deleter函數。在__dict__中設置與此類描述符對象具有相同名稱的鍵將被忽略,因爲數據描述符會導致屬性查找完全繞過__dict__

object.__setattr__()知道如何處理數據描述符,這就是爲什麼你應該調用它。

+0

也許「在'__dict__'中爲這樣的對象設置一個鍵將被忽略」應該是「爲其__dict__中的類使用數據描述符的對象設置鍵將被忽略」to讓它更清晰? –

+0

@sunqingyao:所討論的'對象'是類中的數據描述符。 –

相關問題