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

时间:2014-08-24 11:34:21

标签: python recursion exception-handling

我在行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 个答案:

答案 0 :(得分:5)

hasattr调用__getattr__会导致递归。 From the docs

  

hasattr(object, name)参数是一个对象和一个字符串。如果字符串是对象属性之一的名称,则结果为True,否则返回False。 (这是通过调用getattr(object,name)并查看是否引发异常来实现的。) [我的重点]

解决此问题的一种方法可能是用if hasattr(self, '_ubuffer')替换if '_ubuffer' in self.__dict__

答案 1 :(得分: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))

答案 2 :(得分:0)

您可以使用超类实现进行常规属性访问:

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))