为什么重新定义 __getattr__() 的对象会抛出 TypeError?
Why does an object with redefined __getattr__() throws TypeError?
这是代码
class MyTest:
def __init__(self):
pass
def __getattr__(self, attr):
pass
t = MyTest()
print 'my test object: %r' %t
因此打印会触发 TypeError: 'NoneType' object is not callable
而我只想查看对象是否存在。
当然,此代码不是很有用。但是我在大型代码库中有一个像这样的存根 class 所以我做了
if module and module.class and module.class.propery:
# do something with that property
...
并得到一个 Type Error: 'NoneType' object is not callable
但该线路没有调用任何东西!我猜 python 正在幕后隐式调用一些函数。
奇怪的是,如果 class 继承自 Object
,则不会发生这种情况
怎么回事?
在 python 2 中,使用旧式 类,当您尝试在对象上调用 __repr__
(打印时)时,您会调用 __getattr__
。
因为你猛烈地破坏了这个方法,它 returns None
和 python 试图调用 None
(因为它期待一个方法被返回)
尝试调用 object.__getattr__
,这会起作用:
class MyTest:
def __init__(self):
pass
def __getattr__(self, attr):
print(attr) # so we see why getattr is called
return object.__getattr__(self,attr) # so it doesn't crash (neither it is useful...)
t = MyTest()
print ('my test object: %r' %t)
打印:
__repr__
my test object: <__main__.MyTest instance at 0x00000000031B3808>
这是一个特定的 python 2/旧式对象问题。 Python 3 个或新式对象的行为不同
在旧式 class 中,__getattr__
用于更多种类的属性访问,包括魔术方法。 %
运算符试图调用 t.__repr__()
以填充 %r
占位符,但 t.__repr__
由 t.__getattr__('__repr__')
求值,returns None
.
在if
的情况下,调用了不同的魔术方法,但出现了同样的问题。
>>> class Foo:
... def __getattr__(self, attr):
... print(attr)
...
>>> f = Foo():
>>> if f:
... pass
__nonzero__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable
使用新样式 class,仅当无法通过正常方法找到属性时才调用 __getattr__
(检查实例或任何实例的 __dict__
属性class 在实例的 MRO 中)。
>>> class Foo(object):
... def __init__(self):
... self.x = 3
... def __getattr__(self, attr):
... print(attr)
...
>>> f = Foo()
>>> if f:
... pass
...
>>> f.x
3
>>> f.y
y
在 if f
的情况下,f
本身没有实现 __nonzero__
或 __len__
,它的父级 object
也没有实现,但是在那情况下,不使用任何属性;事实上, f
是一个对象。在f.x
中,x
是在实例的属性dict中找到的,所以直接返回它的值。只有未由 f
、Foo
或 object
定义的 y
调用对 __getattr__
.
的调用
这是代码
class MyTest:
def __init__(self):
pass
def __getattr__(self, attr):
pass
t = MyTest()
print 'my test object: %r' %t
因此打印会触发 TypeError: 'NoneType' object is not callable
而我只想查看对象是否存在。
当然,此代码不是很有用。但是我在大型代码库中有一个像这样的存根 class 所以我做了
if module and module.class and module.class.propery:
# do something with that property
...
并得到一个 Type Error: 'NoneType' object is not callable
但该线路没有调用任何东西!我猜 python 正在幕后隐式调用一些函数。
奇怪的是,如果 class 继承自 Object
怎么回事?
在 python 2 中,使用旧式 类,当您尝试在对象上调用 __repr__
(打印时)时,您会调用 __getattr__
。
因为你猛烈地破坏了这个方法,它 returns None
和 python 试图调用 None
(因为它期待一个方法被返回)
尝试调用 object.__getattr__
,这会起作用:
class MyTest:
def __init__(self):
pass
def __getattr__(self, attr):
print(attr) # so we see why getattr is called
return object.__getattr__(self,attr) # so it doesn't crash (neither it is useful...)
t = MyTest()
print ('my test object: %r' %t)
打印:
__repr__
my test object: <__main__.MyTest instance at 0x00000000031B3808>
这是一个特定的 python 2/旧式对象问题。 Python 3 个或新式对象的行为不同
在旧式 class 中,__getattr__
用于更多种类的属性访问,包括魔术方法。 %
运算符试图调用 t.__repr__()
以填充 %r
占位符,但 t.__repr__
由 t.__getattr__('__repr__')
求值,returns None
.
在if
的情况下,调用了不同的魔术方法,但出现了同样的问题。
>>> class Foo:
... def __getattr__(self, attr):
... print(attr)
...
>>> f = Foo():
>>> if f:
... pass
__nonzero__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable
使用新样式 class,仅当无法通过正常方法找到属性时才调用 __getattr__
(检查实例或任何实例的 __dict__
属性class 在实例的 MRO 中)。
>>> class Foo(object):
... def __init__(self):
... self.x = 3
... def __getattr__(self, attr):
... print(attr)
...
>>> f = Foo()
>>> if f:
... pass
...
>>> f.x
3
>>> f.y
y
在 if f
的情况下,f
本身没有实现 __nonzero__
或 __len__
,它的父级 object
也没有实现,但是在那情况下,不使用任何属性;事实上, f
是一个对象。在f.x
中,x
是在实例的属性dict中找到的,所以直接返回它的值。只有未由 f
、Foo
或 object
定义的 y
调用对 __getattr__
.