473,800 Members | 2,640 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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.

Feb 14 '06 #1
8 1904
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(Par rot, "thing") is Parrot.thing
True
getattr(Par rot, "__dict__") is Parrot.__dict__
False

hint:
getattr(object, '__dict__')

<dictproxy object at 0x2aaaaab2ff30>
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom. gro'.split('@')])"
Feb 14 '06 #2
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

Feb 14 '06 #3
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(Pa rrot, "thing") is Parrot.thing


True
>getattr(Pa rrot, "__dict__") is Parrot.__dict__


False

hint:
getattr(object, '__dict__')

<dictproxy object at 0x2aaaaab2ff30>


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.

Feb 14 '06 #4
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.

Feb 14 '06 #5
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.__dic t__) == id(Parrot.__dic t__) 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

Feb 14 '06 #6
Steven D'Aprano wrote:
>>class Parrot(object):

... thing = [1,2,3]
...

>>getattr(Pa rrot, "thing") is Parrot.thing

True

>>getattr(Pa rrot, "__dict__") is Parrot.__dict__

False

hint:
> getattr(object, '__dict__')

<dictproxy object at 0x2aaaaab2ff30>


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>

Feb 14 '06 #7

"Carl Banks" <in**********@a erojockey.com> wrote in message
news:11******** *************@g 44g2000cwa.goog legroups.com...
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.__dic t__) == id(Parrot.__dic t__) 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

Feb 15 '06 #8
On Tue, 14 Feb 2006 22:24:12 -0500, rumours say that "Terry Reedy"
<tj*****@udel.e du> might have written:
> id(Parrot.f) == id(Parrot.f)

True
> id(Parrot.__dic t__) == id(Parrot.__dic t__)

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
Feb 16 '06 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
1874
by: Ed Young | last post by:
Here is an example of the behavior: ------- code start ----------------------------------- #!/usr/bin/python #bugtest - test of class attribute initiation class Config: a = 1 b = 2 c = 3
90
4003
by: Mark Hahn | last post by:
"Michael Geary" <Mike@Geary.com> wrote ... >Does anyone have some sample code where obj$func() would be used? > (Apologies if I missed it.) There have been so many messages about delegation and binding since Greg originally posted his meowing cat message that it's hard to remember what the original problem was that Greg pointed out. At that time Prothon had no solution for the problem. Now there is a released solution but it is...
7
2224
by: Chris | last post by:
hello, I have question about the re.I option for Regular Expressions: >>> import re >>> re.findall('x', '1x2X3', re.I) as expected finds both lower and uppercase x
13
4188
by: Pierre | last post by:
Hi, Sorry in advance, english is not my main language :/ I'd like to customize the result obtained by getattr on an object : if the object has the requested property then return it BUT if the object doesn't has actually this property return something else. In my case, I can't use getattr(object, property, default_value).
2
5563
by: indiarocks | last post by:
Just a basic question .... When using getattr for a specific method from a different class, can we somehow tell getattr to do a case-insensitive search. Say for eg. m = getattr(obj.__class__,'SetupClass') where obj is a object of a specific class. If SetupClass is declared as setUPClass or in any other way, the return value of m is going to be None, so can this be avoided in any way Thanks
12
2430
by: Ivan Voras | last post by:
While using PyGTK, I want to try and define signal handlers automagically, without explicitly writing the long dictionary (i.e. I want to use signal_autoconnect()). To do this, I need something that will inspect the current "self" and return a dictionary that looks like: { "method_name" : self.method_name }
3
1969
by: Rotlaus | last post by:
Hello, lets assume i have some classes: class A(object): def __init__(self): b = B() class B(object): def __init__(self):
8
7991
by: Gregor Horvath | last post by:
Hi, class A(object): test = "test" class B(object): a = A() In : B.a.test
4
10488
by: maestro | last post by:
Why are these functions there? Is it somehow more idiomatic to use than to do obj.field ? Is there something you can with them that you can't by obj.field reference?
0
9690
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9551
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10504
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10251
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10033
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9085
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6811
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
2
3764
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2945
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.