Unexpected behaviour of getattr(obj, __dict__)

Carl Banks invalidemail at aerojockey.com
Tue Feb 14 07:31:47 EST 2006


Raymond Hettinger wrote:
> 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


Yes, in fact getattr has nothing to do with it.  To wit:

>>> Parrot.f is Parrot.f
False
>>> Parrot.__dict__ is Parrot.__dict__
False

But wait, it gets weirder.

>>> id(Parrot.f) == id(Parrot.f)
True
>>> id(Parrot.__dict__) == id(Parrot.__dict__)
True

But that's not all.  Redefine Parrot as:

class Parrot(object):
    def f(self): pass
    def g(self): pass

Then,

>>> id(Parrot.f) == id(Parrot.g)
True


your-milage-may-vary-ly yr's,

Carl Banks




More information about the Python-list mailing list