Re: Unexpected behaviour of getattr(obj, __dict__)
On Tue, 14 Feb 2006 22:24:12 -0500, rumours say that Terry Reedy [EMAIL PROTECTED] might have written: id(Parrot.f) == id(Parrot.f) True id(Parrot.__dict__) == id(Parrot.__dict__) True A wrapper is created and passed to id() which returns an int object while releasing the wrapper back to the free list. Then another wrapper is created in the same chunk of memory and passed to id, which returns an int of the same value for comparison. The language ref only guarantees uniqueness of ids at any particular instant and allows reuse of ids of deallocated objects. I half seriously think the lib ref entry for id() should have a warning that naive use can mislead. Actually, you more-or-less just wrote what could (I also think should) be included in the docs. -- TZOTZIOY, I speak England very best. Dear Paul, please stop spamming us. The Corinthians -- http://mail.python.org/mailman/listinfo/python-list
Unexpected behaviour of getattr(obj, __dict__)
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. This is true for some attributes, but not for __dict__. I don't know if there are other examples. Why is this? Is there some documentation I can read up about this? I've tried searching, but can't find anything useful. -- Steven. -- http://mail.python.org/mailman/listinfo/python-list
Re: Unexpected behaviour of getattr(obj, __dict__)
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 hint: getattr(object, '__dict__') dictproxy object at 0x2ab2ff30 -- bruno desthuilliers python -c print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for p in '[EMAIL PROTECTED]'.split('@')]) -- http://mail.python.org/mailman/listinfo/python-list
Re: Unexpected behaviour of getattr(obj, __dict__)
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
Re: Unexpected behaviour of getattr(obj, __dict__)
On Tue, 14 Feb 2006 04:11:52 -0800, 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. [penny drops] That would certainly explain it. Is there a canonical list of attributes which are wrapped in this way? I suppose not... it is probably the sort of thing which is subject to change as Python evolves. I knew methods were wrapped, but I didn't know they were wrapped on the fly, nor did I connect the two phenomena. Thank you for the concise and simple answer. -- Steven. -- http://mail.python.org/mailman/listinfo/python-list
Re: Unexpected behaviour of getattr(obj, __dict__)
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Unexpected behaviour of getattr(obj, __dict__)
Steven D'Aprano wrote: class Parrot(object): ... thing = [1,2,3] ... getattr(Parrot, thing) is Parrot.thing True getattr(Parrot, __dict__) is Parrot.__dict__ False hint: getattr(object, '__dict__') dictproxy object at 0x2ab2ff30 That doesn't answer the question, it just re-words it. Why is the dictproxy returned by getattr a different instance from the dictproxy that you get when you say object.__dict__? because it's created on the fly: Parrot.__dict__ dictproxy object at 0x009818B0 Parrot.__dict__ dictproxy object at 0x00981A10 Parrot.__dict__ dictproxy object at 0x009818B0 Parrot.__dict__ dictproxy object at 0x00981A10 Parrot.__dict__ dictproxy object at 0x009818B0 Parrot.__dict__ dictproxy object at 0x00981A10 Parrot.__dict__ dictproxy object at 0x009818B0 Parrot.__dict__ dictproxy object at 0x00981A10 Parrot.__dict__ dictproxy object at 0x009818B0 Parrot.__dict__ dictproxy object at 0x00981A10 Parrot.__dict__ dictproxy object at 0x009818B0 the object itself contains a dictionary. /F -- http://mail.python.org/mailman/listinfo/python-list
Re: Unexpected behaviour of getattr(obj, __dict__)
On Tue, 14 Feb 2006 13:03:17 +0100, bruno at modulix 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 hint: getattr(object, '__dict__') dictproxy object at 0x2ab2ff30 That doesn't answer the question, it just re-words it. Why is the dictproxy returned by getattr a different instance from the dictproxy that you get when you say object.__dict__? -- Steven. -- http://mail.python.org/mailman/listinfo/python-list
Re: Unexpected behaviour of getattr(obj, __dict__)
Carl Banks [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] But wait, it gets weirder. Not weird at all. Just an artifact of CPython's storage recycling algorithm. id(Parrot.f) == id(Parrot.f) True id(Parrot.__dict__) == id(Parrot.__dict__) True A wrapper is created and passed to id() which returns an int object while releasing the wrapper back to the free list. Then another wrapper is created in the same chunk of memory and passed to id, which returns an int of the same value for comparison. The language ref only guarantees uniqueness of ids at any particular instant and allows reuse of ids of deallocated objects. I half seriously think the lib ref entry for id() should have a warning that naive use can mislead. 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 Same thing. The wrapper content is not relevant as long as it uses the same memory block. Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list