Why does __getattribute__ fail with: TypeError: 'NoneType' object is not callable

Why does __getattribute__ fail with: TypeError: 'NoneType' object is not callable

这是我在这里的第一个问题,也是我在 Python 中的第一个项目。

我正在尝试存储名为 Ip500Device:

的 class 的实例
class Ip500Device(object):

    list = []
    def __init__(self, shortMac, mac, status, deviceType):
        self.__shortMac =shortMac
        self.__mac=mac
        self.__status=status
        self.__deviceType=deviceType
        self.__nbOfObjects=0
        Ip500Device.list.append(self)    

    def __getattribute__(self, att):
        if att=='hello':
            return 0

这第一个测试只是一个'hello',但之后我想得到所有的属性。

来自另一个 class,我正在创建设备对象并将它们添加到列表中:

self.__ip500DevicesLst.append(Ip500Device.Ip500Device(lst[0],lst[1],lst[2],lst[3]))
for abcd in self.__ip500DevicesLst:
       print abcd.__getattribute__('hello')

但是当我尝试打印时,程序returns这条消息:

TypeError: 'NoneType' object is not callable

我不太明白如何在 Python 中存储 class 个实例。

print abcd.__getattribute__('hello')

abcd.__getattribute__ 不是 __getattribute__ 方法。当您尝试计算 abcd.__getattribute__ 时,您实际上是在调用

type(abcd).__getattribute__(abcd, '__getattribute__')

which returns None,然后您尝试调用它,就好像它是一个方法一样。

错误发生是因为 所有 属性都调用了 __getattribute__,并且您已将其定义为 return None 以外的所有属性"hello"。由于 __getattribute__ 本身就是一个属性,当您尝试调用它时,您将得到一个 TypeError.

这个问题可以通过为未处理的属性调用 base-class 方法来解决:

>>> class Ip500Device(object):
...     def __getattribute__(self, att):
...         print('getattribute: %r' % att)
...         if att == 'hello':
...             return 0
...         return super(Ip500Device, self).__getattribute__(att)
...
>>> abcd = Ip500Device()
>>> abcd.__getattribute__('hello')
getattribute: '__getattribute__'
getattribute: 'hello'
0

但是,最好定义 __getattr__,因为它只针对尚不存在的属性调用:

>>> class Ip500Device(object):
...     def __getattr__(self, att):
...         print('getattr: %r' % att)
...         if att == 'hello':
...             return 0
...         raise AttributeError(att)
...
>>> abcd = Ip500Device()
>>> abcd.hello
getattr: 'hello'
0
>>> abcd.foo = 10
>>> abcd.foo
10

最后,请注意,如果您只想按名称访问属性,则可以使用内置的 getattr 函数:

>>> class Ip500Device(object): pass
...
>>> abcd = Ip500Device()
>>> abcd.foo = 10
>>> getattr(abcd, 'foo')
10