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 -- http://mail.python.org/mailman/listinfo/python-list