she*_*ats 177 python getproperty getattr
我想覆盖__getattr__
类上的方法来做一些奇特的事情,但我不想打破默认行为.
这样做的正确方法是什么?
Mic*_*son 257
覆盖__getattr__
应该没问题 - __getattr__
只作为最后的手段调用,即如果实例中没有与名称匹配的属性.例如,如果您访问foo.bar
,则__getattr__
只有在foo
没有调用属性的情况下才会被调用bar
.如果属性是您不想处理的属性,请引发AttributeError
:
class Foo(object):
def __getattr__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
raise AttributeError
Run Code Online (Sandbox Code Playgroud)
但是,与之不同的是__getattr__
,__getattribute__
将首先调用(仅适用于新样式类,即从对象继承的类).在这种情况下,您可以保留默认行为,如下所示:
class Foo(object):
def __getattribute__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
return object.__getattribute__(self, name)
Run Code Online (Sandbox Code Playgroud)
小智 32
class A(object):
def __init__(self):
self.a = 42
def __getattr__(self, attr):
if attr in ["b", "c"]:
return 42
raise AttributeError("%r object has no attribute %r" %
(self.__class__.__name__, attr))
Run Code Online (Sandbox Code Playgroud)
>>> a = A()
>>> a.a
42
>>> a.b
42
>>> a.missing
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __getattr__
AttributeError: 'A' object has no attribute 'missing'
>>> hasattr(a, "b")
True
>>> hasattr(a, "missing")
False
Run Code Online (Sandbox Code Playgroud)
Jos*_*uis 10
要扩展迈克尔答案,如果要保持使用的默认行为__getattr__
,可以这样做:
class Foo(object):
def __getattr__(self, name):
if name == 'something':
return 42
# Default behaviour
return self.__getattribute__(name)
Run Code Online (Sandbox Code Playgroud)
现在,异常消息更具描述性:
>>> foo.something
42
>>> foo.error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __getattr__
AttributeError: 'Foo' object has no attribute 'error'
Run Code Online (Sandbox Code Playgroud)