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