我有一些奇怪的行为造成的错误。我可能从根本上缺少一些关于函数属性语义的东西。或者它可能是一个错误。我在
$ python
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
[GCC 4.5.2] on linux2
首先,我定义一个类,并为其中一个方法添加一个属性。
>>> class Foo(object):
... def bar(self):
... pass
... bar.xyzzy = 'magic'
...
现在我可以看到Foo.bar
>>> hasattr(Foo.bar, 'xyzzy')
True
我可以找回它。
>>> Foo.bar.xyzzy
'magic'
>>> getattr(Foo.bar, 'xyzzy')
'magic'
但我不能删除它。
>>> del Foo.bar.xyzzy
Traceback (most recent call last):
...
AttributeError: 'instancemethod' object has no attribute 'xyzzy'
>>> delattr(Foo.bar, 'xyzzy')
Traceback (most recent call last):
...
AttributeError: 'instancemethod' object has no attribute 'xyzzy'
任何想法为什么?我认为这与Foo.bar
在这里被报告为'instancemethod'这一事实有关,而不是如果你只问Foo.bar
是什么的未绑定方法。但我不确定这是否是预期的副作用,如果我误解了某些内容,或者是否存在错误。
答案 0 :(得分:6)
你应该这样做:
del Foo.bar.im_func.xyzzy
访问真实方法im_func
需要Foo.bar
,instancemethod
是一种处理自动传递的装饰器......
在您使用xyzzy
成功访问Foo.bar
getattr
属性时,我可能已经从您的问题中了解到这一点,并且您发现了delattr
don'这一事实t以相同的方式行事,其原因是内部getattr
调用类的__getattribute__
(和__getattr__
)以及第一个参数中对象的所有父类,直到它找到属性或提高AttributeError
,hasattr
相同,相当于:
def hasattr(obj, attr):
try:
getattr(obj, attr)
except AttributeError:
return False
return True
另一方面delattr
只有在传递的属性是对象命名空间的一部分(不是his class他的父母类)时才会成功,因为安全原因(你不想(< strong>尝试)删除object的属性不是你:-)。
答案 1 :(得分:5)
您的问题不在于函数属性,而在于实例方法和函数之间的区别。尝试:
class A(object):
def foo(self):
pass
foo.bar = 'magic'
del A.__dict__['foo'].bar
它会正常工作。这是因为在这里,您实际上是获取函数对象foo
,而不是实例方法foo
。
这种区别在Python 3中消失了,你正在尝试的将在实例方法上正常工作。有关详细信息,请参阅this mailing list thread。