Python 为什么具有重定义的uu getattr_uuu()的对象会抛出TypeError?
这是密码Python 为什么具有重定义的uu getattr_uuu()的对象会抛出TypeError?,python,python-2.7,typeerror,setattr,Python,Python 2.7,Typeerror,Setattr,这是密码 class MyTest: def __init__(self): pass def __getattr__(self, attr): pass t = MyTest() print 'my test object: %r' %t 所以print会触发一个TypeError:“NoneType”对象不可调用,而我只想看看对象是否存在。 当然,这段代码不是很有用。但是我在一个大的代码库中有一个这样的存根类,所以我做了 if modu
class MyTest:
def __init__(self):
pass
def __getattr__(self, attr):
pass
t = MyTest()
print 'my test object: %r' %t
所以print会触发一个TypeError:“NoneType”对象不可调用,而我只想看看对象是否存在。
当然,这段代码不是很有用。但是我在一个大的代码库中有一个这样的存根类,所以我做了
if module and module.class and module.class.propery:
# do something with that property
...
并得到一个类型错误:“NoneType”对象不可调用
,但该行不调用任何东西!我猜python是在幕后隐式调用某些函数
奇怪的是,如果类继承自对象
发生了什么事?在python 2中,使用旧式类,当您尝试在对象上调用\uuuuurepr\uuuuuu
(打印)时,调用了\uuuuugetattr\uuuuuu
因为您猛烈地打断了这个方法,所以它返回None
,python试图调用None
(因为它希望返回一个方法)
尝试调用对象。\uuuu getattr\uuuuu
,这样做可以:
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>
报告__
我的测试对象:
这是一个特定的Python2/旧式对象问题。Python 3或新样式的对象的行为与旧样式的类不同,\uuu getattr\uuuu
用于更广泛的属性访问,包括魔术方法。%
运算符试图调用t.\uuuu repr\uuuuu()
以填充%r
占位符,但t.\uu repr\uuuuuu
由t.计算。uu getattr\uuuuuu(“\uu repr\uuuuuuu”)
,它返回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
在如果f
的情况下,f
本身不实现\uuuu非零\uuuuu
或\uuuu len\uuuu
,其父对象也不实现,但在这种情况下,不使用任何属性;事实上,f
是一个对象。在f.x
中,实例的属性dict中找到了x
,因此直接返回其值。只有y
,它不是由f
、Foo
或object
定义的,调用\uuuu getattr\uuuuuu
\uu getattr\uuuuuu
应该返回一些东西,而不是None
@Jean Françoisfare<代码>无
是“某物”!您的字符串格式化操作尝试访问t
的\uuuu repr\uuuuu
属性,并且由于您使用的是旧式类(您没有从对象
继承),\uu getattr\uuuu
将返回无
,而不是实际返回需要调用的方法。不要使用旧式类。因此'if t'也调用\uu repr\uu()
?不,但是在布尔上下文中计算t
会调用一些东西。使用Jean-François Fabre的建议,即在返回任何内容之前将参数打印到\uuuu getattr\uuuuu
,应该显示t.\uu非零
被调用以确定t
是否真实。
>>> 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