Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can someone explain Python hasattr/delattr on a method attribute?

Tags:

python

I've got a bug caused by some weird behavior. I might be fundamentally missing something about the semantics of function attributes. Or it may be a bug. I'm on

$ python
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53) 
[GCC 4.5.2] on linux2

First I define a class, and add an attribute to one of its methods.

>>> class Foo(object):
...    def bar(self):
...        pass
...    bar.xyzzy = 'magic'
...

Now I can see that exists on Foo.bar

>>> hasattr(Foo.bar, 'xyzzy')
True

And I can retrieve it.

>>> Foo.bar.xyzzy
'magic'

>>> getattr(Foo.bar, 'xyzzy')
'magic'

But I can't delete it.

>>> 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'

Any ideas why? I assume it is something to do with the fact that Foo.bar is being reported as an 'instancemethod' here, rather than an unbound method if you just ask what Foo.bar is. But I'm not sure if it is an expected side-effect, if I'm misunderstanding something, or if there's a bug.

like image 888
Ian Avatar asked Feb 24 '26 06:02

Ian


1 Answers

You should do :

del Foo.bar.im_func.xyzzy

The im_func is needed to access the real method Foo.bar, the instancemethod is a kind of decorator that deal with passing self automatically ... .


As i may have understand from your question while you was successfully accessing the xyzzy attribute of Foo.bar using getattr and like you came across the fact that delattr don't act the same way, and the reason of that is that internally getattr call the __getattribute__ (and __getattr__) of the class and all the parent class of the object in the first argument until it find the attribute or raise an AttributeError, the same for hasattr which is equivalent to:

def hasattr(obj, attr):
    try:
        getattr(obj, attr)
    except AttributeError:
        return False
    return True

In the other hand delattr will only succeed if the attribute passed is part of the object namespace (not his class neither his parents class) because of safety reasons (you don't want to (try) to delete an attribute of object wouldn't you :-).

like image 191
mouad Avatar answered Feb 25 '26 20:02

mouad



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!