Python Override-Class属性-getter
我定义了一个调试类,如下所示:Python Override-Class属性-getter,python,python-3.x,Python,Python 3.x,我定义了一个调试类,如下所示: _debug = False class Debug: DrawOutlines = True InvinciblePlayer = True 我想重写Debug类,这样如果_Debug为False,Debug的任何类属性(存在)都将为False。为了更改类属性的访问方式,我应该覆盖哪些功能 编辑: 我知道简单地重写\uuuu getattribute\uuuu对类属性不起作用: >>> _debug = False Fals
_debug = False
class Debug:
DrawOutlines = True
InvinciblePlayer = True
我想重写Debug
类,这样如果_Debug为False,Debug的任何类属性(存在)都将为False。为了更改类属性的访问方式,我应该覆盖哪些功能
编辑:
我知道简单地重写\uuuu getattribute\uuuu
对类属性不起作用:
>>> _debug = False
False
>>> class Debug:
... DrawOutlines = True
...
... def __getattribute__(self, name):
... return _debug and object.__getattribute__(self, name)
...
>>> Debug.DrawOutlines
True
>>> Debug.cake
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'Debug' has no attribute 'cake'
>>\u debug=False
假的
>>>类调试:
... DrawOutlines=真
...
... def uu getattribute_uu(self,name):
... 返回调试和对象。获取属性(self,name)
...
>>>Debug.DrawOutlines
真的
>>>调试蛋糕
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:类型对象“Debug”没有属性“cake”
在这种情况下,我需要一个元类吗?您可以重写
\uuuuuGetAttribute\uuuuuuu
来拦截所有的属性访问,或者\uuuuuuuGetAttr\uuuuuuuuuu
来仅为不存在的属性调用:
_debug = True
class A(object):
def __getattribute__(self, attr):
if _debug:
print attr
return object.__getattribute__(self, attr)
是的,您需要一个元类,因为如果您在类Debug(注意,它必须是一个新样式的类)中定义
\uuuu getattribute\uuuu
,Python将调用该元类来对Debug实例进行属性查找,而不是对Debug本身进行属性查找
这是有意义的,因为Debug.\uuuuu getattribute\uuuuu
被定义为在Debug实例上操作,而不是类Debug。(您可以想象定义一个classmethod\uuuu getattribute\uuuu
,但我找不到任何证据表明Python有任何机制可以调用这样的东西。)
这里我想到的第一件事是添加另一个\uuuuu getattribute\uuuu
,Python将在其中查找调试类属性查找,也就是说,在调试类作为实例的类中:Debug.\uuuu class\uu.\uuuu getattribute\uuu
这确实存在,并且按照您的预期工作:
>>> 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'
因此,归结起来,类的默认类实现是
type
,因此类属性的默认属性查找器上限是type.\uuuu getattribute.\uuuu
,您不能直接修改或替换type.\uu uu getattribute.\uuu
,但可以使用元类机制替换type
,并且,在上面的示例中,将其替换为类型的子类,该子类具有所需的\uuu getattribute\uuu
。这并没有解决它是类属性的问题,因为它只在实例上工作。这里是否需要元类?是的,如果您编写元类,并编写元类`\uuu getattr\uuu
方法,它将适用于类属性。它可能不适用于特殊的dunder方法,例如\uuuuu add\uuuuuu
和\uuuuuuu eq\uuuuu
,因为Python的机器库会覆盖对这些特殊属性的访问,以提高效率。它只是使用了一个对象并使用了一个类的单个实例,就像这样。然而,我最初的问题是重写类属性,而不是对象属性。如果您编辑此答案以指定我可以使用单个对象(我的示例没有self.
属性),或者提供了一个元类示例,我可以“接受”它。如前所述,您的\uuuu getattribute\uuuuu
方法不会被调用,因为调试不会从对象继承,即它是一个旧式类,而\uuu getattribute\uu
仅适用于新样式的类。但是,即使解决了这个问题,您真正的问题仍然存在:该方法将被调用以查找调试实例的属性,而不是类Debug。@metamatt Python 3.x类将自动从对象继承。
>>> 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'
_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