Why property works only for objects?
Alex Martelli
aleaxit at yahoo.com
Sat Mar 11 15:07:59 EST 2006
Michal Kwiatkowski <ruby at no.spam> wrote:
> class C(object):
> __dict__ = {}
>
> obj = C()
> obj.a = 7
> obj.__dict__ = {}
> print object.__getattribute__(obj, '__dict__')
> print object.__getattribute__(C, '__dict__')
> print obj.a # => 7 !!!
>
> First print returns "{}" and the second returns
>
> {'__dict__': {},
> '__module__': '__main__',
> '__weakref__': <attribute '__weakref__' of 'C' objects>,
> '__doc__': None}
>
> Neither of them have "a" attribute. How come obj.a doesn't raise an
> exception? Where obj.a is kept?
It's easier to trace if you use a unique value rather than 7 ...:
>>> class C(object):
... __dict__ = {}
...
>>> obj = C()
>>> obj.a = object()
>>> import gc
>>> gc.get_referrers(obj.a)
[{'a': <object object at 0x3d438>}]
so, at this point, you know that obj.a is kept in a dictionary where
it's the only value. That's the dictionary you would USUALLY be able to
get to as obj.__dict__, but...:
>>> obj.__dict__
{}
...the presence of '__dict__' as an entry in C is confusing the issue,
because that's what you get in this case as obj.__dict__.
C.__dict__ gives you a dictproxy, not a real dict, by the way:
>>> obj.__dict__ is C.__dict__['__dict__']
True
The funny thing is that builtins like var, which should know better,
also get fooled...:
>>> vars(obj)
{}
>>> vars(obj) is C.__dict__['__dict__']
True
...and so does the assignment to obj.__dict__...:
>>> obj.__dict__ = {}
>>> gc.get_referrers(obj.a)
[{'a': <object object at 0x3d438>, '__dict__': {}}]
Now, both obj.a and obj.__dict__ are entries in a dictionary where
they're the only two entries -- exactly the dictionary that would
NORMALLY be obj.__dict__.
I think a fair case can be made that you've found a bug in Python here:
the existence of that __dict__ in C's class body is clearly causing
unintended anomalies. Fortunately, getattr and friends don't in fact
get confused, but vars does, as does assignment to obj.__dict__...
Alex
More information about the Python-list
mailing list