467,208 Members | 1,358 Online
Bytes | Developer Community
Ask Question

Home New Posts Topics Members FAQ

Post your question to a community of 467,208 developers. It's quick & easy.

Inconsistent behavior of descriptors


I've noticed that the order of attribute lookup is inconsistent
when descriptor is used. property instance takes precedence of
instance attributes:
class A(object): .... def _get_attr(self):
.... return self._attr
.... attr = property(_get_attr)
.... a=A()
a.__dict__ {} a.__dict__['attr']=1
a.__dict__ {'attr': 1} a.attr Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in _get_attr
AttributeError: 'A' object has no attribute '_attr'

But it doesn't when I use custom class of descriptor:
class descr(object): .... def __get__(self, inst, cls):
.... return inst._attr
.... class B(object): .... attr = descr()
.... b=B()
b.__dict__ {} b.__dict__['attr']=1
b.__dict__ {'attr': 1} b.attr 1

Subclasses of property behave like property itself:
class descr2(property): .... def __get__(self, inst, cls):
.... return inst._attr
.... class C(object): .... attr = descr2()
.... c=C()
c.__dict__ {} c.__dict__['attr']=1
c.__dict__ {'attr': 1} c.attr

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in __get__
AttributeError: 'C' object has no attribute '_attr'

Is it an undocumented feature or I have to submit a bug report?

--
Denis S. Otkidach
http://www.python.ru/ [ru]
Jul 18 '05 #1
  • viewed: 1566
Share:
2 Replies

"Denis S. Otkidach" <od*@strana.ru> wrote in message
news:ma**********************************@python.o rg...

I've noticed that the order of attribute lookup is inconsistent
when descriptor is used. property instance takes precedence of
instance attributes:
class A(object): ... def _get_attr(self):
... return self._attr
... attr = property(_get_attr)
... a=A()
a.__dict__ {} a.__dict__['attr']=1
a.__dict__ {'attr': 1} a.attr Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in _get_attr
AttributeError: 'A' object has no attribute '_attr'

But it doesn't when I use custom class of descriptor:
class descr(object): ... def __get__(self, inst, cls):
... return inst._attr
... class B(object): ... attr = descr()
... b=B()
b.__dict__ {} b.__dict__['attr']=1
b.__dict__ {'attr': 1} b.attr 1

Subclasses of property behave like property itself:
class descr2(property): ... def __get__(self, inst, cls):
... return inst._attr
... class C(object): ... attr = descr2()
... c=C()
c.__dict__ {} c.__dict__['attr']=1
c.__dict__ {'attr': 1} c.attr
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in __get__
AttributeError: 'C' object has no attribute '_attr'

Is it an undocumented feature or I have to submit a bug report?


I'm not entirely sure what you're describing, however, I
notice that your descriptor object has a __get__ method,
but no __set__ or __del__ methods. The lookup chain
is quite different for descriptors with only __get__ methods
than it is for descriptors for all three.

In particular, it's intended that instance attributes should
be ignored if there is a data descriptor (that is, a descriptor
with both__get__ and __set__ methods.)

I'm not sure if this applies to your problem.

John Roth
--
Denis S. Otkidach
http://www.python.ru/ [ru]

Jul 18 '05 #2
On Tue, 30 Sep 2003 20:15:10 +0400 (MSD), "Denis S. Otkidach" <od*@strana.ru> wrote:

I've noticed that the order of attribute lookup is inconsistent
when descriptor is used. property instance takes precedence of
instance attributes:
class A(object):... def _get_attr(self):
... return self._attr
... attr = property(_get_attr)
... a=A()
a.__dict__{} a.__dict__['attr']=1
a.__dict__{'attr': 1} a.attrTraceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in _get_attr
AttributeError: 'A' object has no attribute '_attr'

But it doesn't when I use custom class of descriptor:
class descr(object):... def __get__(self, inst, cls):
... return inst._attr
... class B(object):... attr = descr()
... b=B()
b.__dict__{} b.__dict__['attr']=1
b.__dict__{'attr': 1} b.attr1

Subclasses of property behave like property itself:
class descr2(property):... def __get__(self, inst, cls):
... return inst._attr
... class C(object):... attr = descr2()
... c=C()
c.__dict__{} c.__dict__['attr']=1
c.__dict__{'attr': 1} c.attr

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in __get__
AttributeError: 'C' object has no attribute '_attr'

Is it an undocumented feature or I have to submit a bug report?

I think (not having read the above carefully) that it's all documented in

http://users.rcn.com/python/download/Descriptor.htm

(thanks to Raymond Hettinger).

excerpt:
"""
The details of invocation depend on whether obj is an object or a class.
Either way, descriptors only work for new style objects and classes. A
class is new style if it is a subclass of object.

For objects, the machinery is in object.__getattribute__ which
transforms b.x into type(b).__dict__['x'].__get__(b, type(b)). The
implementation works through a precedence chain that gives data
descriptors priority over instance variables, instance variables
priority over non-data descriptors, and assigns lowest priority to
__getattr__ if provided. The full C implementation can be found in
PyObject_GenericGetAttr() in Objects/object.c.

For classes, the machinery is in type.__getattribute__ which transforms
B.x into B.__dict__['x'].__get__(None, B). In pure Python, it looks
like:

def __getattribute__(self, key):
"Emulate type_getattro() in Objects/typeobject.c"
v = object.__getattribute__(self, key)
if hasattr(v, '__get__'):
return v.__get__(None, self)
return v

The important points to remember are:

descriptors are invoked by the __getattribute__ method
overriding __getattribute__ prevents automatic descriptor calls
__getattribute__ is only available with new style classes and objects
object.__getattribute__ and type.__getattribute__ make different calls to __get__.
data descriptors always override instance dictionaries.
non-data descriptors may be overridden by instance dictionaries.
"""

Regards,
Bengt Richter
Jul 18 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by François Pinard | last post: by
1 post views Thread by bk_kl@gmx.de | last post: by
6 posts views Thread by Samuel M. Smith | last post: by
20 posts views Thread by Francine.Neary@googlemail.com | last post: by
8 posts views Thread by Michele Petrazzo | last post: by
2 posts views Thread by DJ Dharme | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.