是的,你需要一个元类,因为如果你在课堂上调试定义__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