是的,你需要一個元類,因爲如果你在課堂上調試定義__getattribute__
(注意,它必須是一個新風格的類),Python將調用它來針對Debug實例的屬性查找,但不會針對調試本身的屬性查找。
這很有道理,因爲Debug.__getattribute__
被定義爲對Debug實例進行操作,而不是類Debug。 (你能想象定義類方法__getattribute__
,但我無法找到任何證據,Python有會調用這樣的事情任何機器。)
我想到這裏的第一件事是添加另一個__getattribute__
那裏的Python會看因爲它用於Debug類屬性查找,即Debug類爲實例的類:Debug.__class__.__getattribute__
。
這確實存在,正如你所期望的工作原理:
>>> Debug.__class__.__getattribute__(Debug, 'Draw')
True
>>> Debug.__class__.__getattribute__(Debug, 'Bogus')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __getattribute__
AttributeError: 'DebugType' object has no attribute 'Bogus'
但它不是修改:
>>> Debug.__class__.__getattribute__ = Debug.__getattribute__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'type'
這似乎只是一個Python實現生活的事實;當這個概念存在時,你不允許修改內建類型的屬性,所以這種方法將不起作用。
然而,元類救援。你可能已經知道如何做到這一點,但是對於其他讀者,我會舉一個例子(this answer還有另外一個例子,我的答案欠一些債務)。
_debug = True
>>> class DebugType(type):
... def __getattribute__(self, name):
... print 'attr lookup for %s' % str(name)
... return _debug and object.__getattribute__(self, name)
...
>>> class Debug(object):
... Draw = True
... __metaclass__ = DebugType
...
>>> _debug
False
>>> Debug.Draw
attr lookup for Draw
False
>>> _debug = True
>>> Debug.Draw
attr lookup for Draw
True
所以熬下來,對於類的默認類的實現是type
,所以默認屬性收看上的類屬性是type.__getattribute__
,你不能修改或直接更換type.__getattribute__
,但可以使用替代type
元類機制,並且如上例所示,將其替換爲type
的子類,該子類具有您想要的__getattribute__
。
正如所寫,您的'__getattribute__'方法不會被調用,因爲調試不會從'object'繼承,即它是一種舊式的類,'__getattribute__'僅適用於新式類。但是,即使修復了這個問題,您的真正問題仍然存在:將在調試實例上調用該方法的屬性查找,但不調試類。 – metamatt 2012-10-26 22:20:55
@metamatt Python 3.x類自動從'object'繼承。 – Darthfett 2012-10-27 18:13:11