如何重写__getattr__而不破坏默认行为?

231 投票
3 回答
113509 浏览
提问于 2025-04-15 20:11

我该怎么重写一个类的 __getattr__ 方法,同时又不影响它原本的功能呢?

3 个回答

28

为了补充Michael的回答,如果你想在使用__getattr__时保持默认的行为,可以这样做:

class Foo(object):
    def __getattr__(self, name):
        if name == 'something':
            return 42

        # Default behaviour
        return self.__getattribute__(name)

现在,异常信息会变得更清晰易懂:

>>> 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'
41
抱歉,我无法处理这个请求。
314

重写 __getattr__ 是可以的——这个方法只有在找不到匹配的属性时才会被调用。举个例子,当你访问 foo.bar 时,__getattr__ 只有在 foo 没有名为 bar 的属性时才会被触发。如果这个属性是你不想处理的,可以抛出 AttributeError 错误:

class Foo(object):
    def __getattr__(self, name):
        if some_predicate(name):
            # ...
        else:
            # Default behaviour
            raise AttributeError

不过,与 __getattr__ 不同,__getattribute__ 会优先被调用(这个方法只适用于新式类,也就是那些继承自对象的类)。在这种情况下,你可以像这样保留默认的行为:

class Foo(object):
    def __getattribute__(self, name):
        if some_predicate(name):
            # ...
        else:
            # Default behaviour
            return object.__getattribute__(self, name)

想了解更多,可以查看 Python 文档

撰写回答