Inconsistent behavior of descriptors

John Roth newsgroups at jhrothjr.com
Tue Sep 30 19:38:09 CEST 2003


"Denis S. Otkidach" <ods at strana.ru> wrote in message
news:mailman.1064938610.30070.python-list at python.org...
>
> 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]
>
>






More information about the Python-list mailing list