有人可以解释方法属性上的Python hasattr / delattr吗?

时间:2011-08-06 15:47:38

标签: python

我有一些奇怪的行为造成的错误。我可能从根本上缺少一些关于函数属性语义的东西。或者它可能是一个错误。我在

$ 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是什么的未绑定方法。但我不确定这是否是预期的副作用,如果我误解了某些内容,或者是否存在错误。

2 个答案:

答案 0 :(得分:6)

你应该这样做:

del Foo.bar.im_func.xyzzy

访问真实方法im_func需要Foo.barinstancemethod是一种处理自动传递的装饰器......


在您使用xyzzy成功访问Foo.bar getattr属性时,我可能已经从您的问题中了解到这一点,并且您发现了delattr don'这一事实t以相同的方式行事,其原因是内部getattr调用类的__getattribute__(和__getattr__)以及第一个参数中对象的所有父类,直到它找到属性或提高AttributeErrorhasattr相同,相当于:

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