Why property works only for objects?

A

Alex Martelli

Michal Kwiatkowski said:
Can you also check my reasoning for getting attributes?

value = obj.attr
* if instance class has __getattribute__, call it
* else: lookup "attr" in all parent classes using class __mro__;
if it's a descriptor call its __get__ method, return its value
otherwise (when descriptor doesn't have __get__, it's unreadable
and AttributeError is raised)
* else: check instance __dict__ for "attr", return it when found
* else: lookup __getattr__ in instance class and call it when found
* else: raise AttributeError

No, the value found in the instance (your second 'else' here) takes
precedence if the descriptor found in the first 'else' is
non-overriding.

The difference:
.... def __get__(*a): return 23
.... .... def __get__(*a): return 23
.... .... def __set__(*a): pass
....

Alex
 
M

Michal Kwiatkowski

Alex Martelli napisa³(a):
No, the value found in the instance (your second 'else' here) takes
precedence if the descriptor found in the first 'else' is
non-overriding.

Oh, right. My mistake comes from the subtle difference between defining
descriptor as a class and by property() builtin (I've tested only second
option and assumed that descriptor without __set__ cannot be rebinded):

class non_overriding(object):
def __get__(*a):
return 12

class C(object):
x = non_overriding()
y = property(lambda s:23)

c = C()

c.x = 4
print c.x # => 4

c.y = 5 # => AttributeError: can't set attribute

IMHO that's not very consistent. Well, probably some code rely on this,
so I just have to live with it.

Thanks for your time and patience in explaining my doubts.

mk
 
A

Alex Martelli

Michal Kwiatkowski said:
Oh, right. My mistake comes from the subtle difference between defining
descriptor as a class and by property() builtin (I've tested only second
option and assumed that descriptor without __set__ cannot be rebinded):

property is always overriding, of course, since type property does have
a property.__set__ (which raises an exception if you build the instance
of property w/o a setter function).
class non_overriding(object):
def __get__(*a):
return 12

class C(object):
x = non_overriding()
y = property(lambda s:23)

c = C()

c.x = 4
print c.x # => 4

c.y = 5 # => AttributeError: can't set attribute

Right: another example of overriding and nonoverriding descriptors.
IMHO that's not very consistent.

How so? Given the lower-level semantics of descriptors (and the
distinction between overriding and non), are you suggesting that
property should not be a type but a factory function able to return
instances of either overriding or non-overriding types? I'm not sure how
that complication would make things "consistent" in your view.
Well, probably some code rely on this,
so I just have to live with it.

Backwards-incompatible changes can be proposed for Python 3.0, if they
lead to a situation that's preferable to what we have now. I just don't
see what you mean about "not very consistent" and what you would prefer
the language and built-ins to be.


Alex
 
M

Michal Kwiatkowski

Alex Martelli napisa³(a):
How so? Given the lower-level semantics of descriptors (and the
distinction between overriding and non), are you suggesting that
property should not be a type but a factory function able to return
instances of either overriding or non-overriding types? I'm not sure how
that complication would make things "consistent" in your view.

Nothing in property documentation suggest that if you don't define
__set__ method, you won't be able to set an attribute. It just states
"Return a property attribute for new-style classes". After reading a bit
about descriptors I've just assumed that property is a handy way to
create (any) descriptors. Learning that it only creates overriding
descriptors was a bit shocking. I'm not suggesting it's bad behavior,
only that it seemed unexpected for an unaware programmer. What at first
glance looked like a shortcut, turned out to be designed for a specific
use case.

mk
 
A

Alex Martelli

Michal Kwiatkowski said:
Alex Martelli napisa?(a):

Nothing in property documentation suggest that if you don't define
__set__ method, you won't be able to set an attribute. It just states
"Return a property attribute for new-style classes". After reading a bit
about descriptors I've just assumed that property is a handy way to
create (any) descriptors. Learning that it only creates overriding
descriptors was a bit shocking. I'm not suggesting it's bad behavior,
only that it seemed unexpected for an unaware programmer. What at first
glance looked like a shortcut, turned out to be designed for a specific
use case.

Yes, I see that the docs at
<http://docs.python.org/lib/built-in-funcs.html> are too curt about
exactly what it is that property returns -- no inconsistency, just
too-scarce docs. The in-development draft at
<http://docs.python.org/dev/lib/built-in-funcs.html> is just about the
same. Why don't you try your hand at making the docs better? As
<http://www.python.org/dev/doc/> points out, *Documentation submissions
are welcome in plain text from contributors without LaTeX knowledge*.

I'd give it a try myself, but doing anything except working on the 2nd
edition of the Nutshell right now would seriously risk ending up
strangled... sigh -- once the Nutshell's 2nd ed is done and over with,
and I've recovered from it, I'll need to get around to serious
contribution to the standard Python docs!-)


Alex
 
J

John J. Lee

Michal Kwiatkowski said:
"Return a property attribute for new-style classes". After reading a bit
about descriptors I've just assumed that property is a handy way to
create (any) descriptors. Learning that it only creates overriding
descriptors was a bit shocking. I'm not suggesting it's bad behavior,
only that it seemed unexpected for an unaware programmer. What at first
glance looked like a shortcut, turned out to be designed for a specific
use case.
[...]

Python builtins (especially the newer ones, perhaps) are often
targetted fairly tightly on particular use cases.


John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,183
Messages
2,570,966
Members
47,514
Latest member
AdeleGelle

Latest Threads

Top