Unexpected behaviour of getattr(obj, __dict__)
Raymond Hettinger
python at rcn.com
Tue Feb 14 07:11:52 EST 2006
Steven D'Aprano wrote:
> I came across this unexpected behaviour of getattr for new style classes.
> Example:
>
> >>> class Parrot(object):
> ... thing = [1,2,3]
> ...
> >>> getattr(Parrot, "thing") is Parrot.thing
> True
> >>> getattr(Parrot, "__dict__") is Parrot.__dict__
> False
>
> I would have expected that the object returned by getattr would be the
> same object as the object returned by standard attribute access.
The returned object is a wrapper created on-the-fly as needed. You've
requested two of them and each wrapper has a different object id but
wraps an identical source.
Contemplate this for a bit:
>>> class Parrot(object):
thing = [1,2,3]
def f(self): pass
>>> getattr(Parrot, 'f') is getattr(Parrot, 'f')
False
>>> getattr(Parrot, '__dict__') is getattr(Parrot, '__dict__')
False
The reason why is evident when you check the object representation. It
shows that your lookup returned a wrapper:
>>> getattr(Parrot, 'f') # creates a function wrapper
<unbound method Parrot.f>
>>> getattr(Parrot, '__dict__') # creates a dictionary wrapper
<dictproxy object at 0x00C41770>
IOW, attribute lookup can do more than just return the result of a
straight-lookup. The underlying mechanism is a deep and interesting
subject. If you want to know more, try this link:
http://users.rcn.com/python/download/Descriptor.htm
Raymond
More information about the Python-list
mailing list