[issue23317] Incorrect description of descriptor invocation in Python Language Reference

2015-01-26 Thread Justin Eldridge

Justin Eldridge added the comment:

Ah, I see how writing a description of this which is both concise and precise
would be difficult, especially for Python 2.

 But the Class Binding description is correct, since if the __get__ method is
 *not* defined on the type (of the descriptor), the descriptor instance itself
 is returned (so explicitly calling type in the equivalent expression would 
 be
 wrong)

I see, but couldn't this also be held against the current equivalent?  That
is, saying A.x is equivalent to A.__dict__['x'].__get__(None, A) is not stricly
true when __get__ isn't defined on type(x).

I think I see now why this is difficult to document cleanly, and the Special
method lookup section of the documentation does a good job of explaining this.
The issue isn't exclusive to descriptors. It affects, for example, the
documentation on rich comparison operators, which says that x == y invokes
x.__eq__(y), when this hasn't quite been true since old-style classes.

So saying x == y is equivalent to x.__eq__(y) isn't really correct, and saying
that it is equivalent to type(x).__eq__(x,y) isn't quite right either, as
implicit invocation may bypass the metaclass's __getattribute__. The latter,
however, seems less wrong. Is there a reason that the former is preferred by
the documentation?

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23317
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23317] Incorrect description of descriptor invocation in Python Language Reference

2015-01-25 Thread Justin Eldridge

New submission from Justin Eldridge:

The section titled Invoking Descriptors in the Python Language Reference [1]
says:

Class Binding
If binding to a new-style class, A.x is transformed into the call: 
A.__dict__['x'].__get__(None, A).

This suggests that __get__ is looked up on the instance of x, when I believe
that it is actually looked up on the type. That is, it's my understanding that
A.x invokes:

type(A.__dict__['x']).__get__(A.__dict__['x'], None, Foo))

Here's some Python 3.4 code demonstrating this:

class A:
pass

class Descriptor:
def __get__(self, obj, cls):
print(Getting!)

A.x = Descriptor()

def replacement_get(obj, cls):
print(This is a replacement.)

A.__dict__['x'].__get__ = replacement_get

Now, writing:

 A.x
Getting!

 A.__dict__['x'].__get__(None, A)
This is a replacement!

 type(A.__dict__['x']).__get__(A.__dict__['x'], None, A)
Getting!

The documentation makes a similar statement about instance binding that also
appears to be incorrect. This is the case in all versions of the document I
could find.

What I believe to be the actual behavior is implied by a later section in the
same document, which states that the implicit invocation of special methods is
only guaranteed to work correctly if the special method is defined on the type,
not the instance.  This suggests that the statements in Invoking Descriptors
aren't quite correct, and while the true behavior is a little more verbose, I
think it would be worthwhile to update the documentation so as to avoid
confusion.

[1]: https://docs.python.org/2/reference/datamodel.html#invoking-descriptors

--
assignee: docs@python
components: Documentation
messages: 234676
nosy: Justin.Eldridge, docs@python
priority: normal
severity: normal
status: open
title: Incorrect description of descriptor invocation in Python Language 
Reference
type: enhancement
versions: Python 2.7, Python 3.2, Python 3.3, Python 3.4, Python 3.5, Python 3.6

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23317
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23317] Incorrect description of descriptor invocation in Python Language Reference

2015-01-25 Thread R. David Murray

R. David Murray added the comment:

I believe that you are correct: special methods are looked up on the type, and 
this is assumed implicitly in the Class Binding description. (This was not 100% 
true in python2, but it is in current python3.)  But the Class Binding 
description is correct, since if the __get__ method is *not* defined on the 
type (of the descriptor), the descriptor instance itself is returned (so 
explicitly calling type in the equivalent expression would be wrong).

This is one of the most complex topics to describe in Python (I still don't 
have it solid in my head and I've been working with Python for years now).  If 
we can come up with clearer wording that is good, but we've tried several times 
already to improve it :(

I don't know what you are referring to for the 'instance binding' that makes 
the same 'mistake', but I suspect it is also covered by the special methods 
are looked up on the type rule.

--
nosy: +r.david.murray
versions:  -Python 3.2, Python 3.3, Python 3.6

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23317
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com