Re: Unexpected behaviour of getattr(obj, __dict__)

2006-02-16 Thread Christos Georgiou
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__)

2006-02-14 Thread Steven D'Aprano
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__)

2006-02-14 Thread bruno at modulix
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__)

2006-02-14 Thread Raymond Hettinger
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__)

2006-02-14 Thread Steven D'Aprano
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__)

2006-02-14 Thread Carl Banks
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__)

2006-02-14 Thread Fredrik Lundh
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__)

2006-02-14 Thread Steven D'Aprano
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__)

2006-02-14 Thread Terry Reedy

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