Python函数中的最大递归深度错误

6 投票
3 回答
1837 浏览
提问于 2025-04-18 18:20

我在这一行 if hasattr(self, '_ubuffer') 出现了最大递归深度错误。有人能帮我看看我哪里出错了吗?这个函数的完整代码是:

def __getattr__(self, name):
        if hasattr(self, '_ubuffer'):
            buffer = object.__getattribute__(self,'_ubuffer')
            if name in buffer.dtype.names:
                return buffer.data[name]
        return object.__getattribute__(self,name)

3 个回答

1

@maciej-gol 提出的这个方法挺不错的,但它没有处理一个常见的情况,就是当父类没有定义自定义的 __getattr__ 方法时(至少在 Python3 中是这样)。为了避免这个问题,最好先使用 __getattribute__ 来检查,因为这个方法总是会被定义,如果检查失败再使用 __getattr__

我建议这样做 如果你事先不知道基类是否实现了自定义的 __getattr__ 方法

def __getattr__(self, name):
    try:
        buffer = self.__getattribute__('_ubuffer')
    except AttributeError:
        try:
            buffer = super().__getattr__('_ubuffer')
        except AttributeError:
            raise AttributeError('Attribute {} not found.'.format(name))

    if name in buffer.dtype.names:
        return buffer.data[name]
    raise AttributeError('Attribute {} not found.'.format(name))

但在大多数情况下,直接使用 __getattribute__ 就足够了:

def __getattr__(self, name):
    try:
        buffer = self.__getattribute__('_ubuffer')
        if name in buffer.dtype.names:
            return buffer.data[name]
        raise AttributeError
    except AttributeError:
        raise AttributeError('Attribute {} not found.'.format(name))
1

你可以使用父类提供的方法来访问普通的属性:

def __getattr__(self, name):
    try:
        buffer = super(MyClass, self).__getattr__('_ubuffer')
    except AttributeError:
        raise AttributeError('Attribute {} not found.'.format(name))

    if name in buffer.dtype.names:
        return buffer.data[name]
    else:
        raise AttributeError('Attribute {} not found.'.format(name))
6

hasattr 这个函数会调用 __getattr__,这可能会导致递归的问题。根据文档

hasattr(object, name) 这个函数需要两个参数,一个是对象,另一个是字符串。如果这个字符串是对象的某个属性的名字,结果就会是 True;如果不是,结果就是 False。(这个过程是通过调用 getattr(object, name) 来实现的,然后看看是否会抛出异常。) [我强调的]

解决这个问题的一种方法是把 if hasattr(self, '_ubuffer') 替换成 if '_ubuffer' in self.__dict__ 这样的写法。

撰写回答