PEP 3155 - Qualified name for classes and functions

Hello,
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)).
I also have a draft implementation that's quite simple (http://hg.python.org/features/pep-3155).
Regards
Antoine.
PEP: 3155 Title: Qualified name for classes and functions Version: $Revision$ Last-Modified: $Date$ Author: Antoine Pitrou solipsis@pitrou.net Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 2011-10-29 Python-Version: 3.3 Post-History: Resolution: TBD
Rationale =========
Python's introspection facilities have long had poor support for nested classes. Given a class object, it is impossible to know whether it was defined inside another class or at module top-level; and, if the former, it is also impossible to know in which class it was defined. While use of nested classes is often considered poor style, the only reason for them to have second class introspection support is a lousy pun.
Python 3 adds insult to injury by dropping what was formerly known as unbound methods. In Python 2, given the following definition::
class C: def f(): pass
you can then walk up from the ``C.f`` object to its defining class::
>>> C.f.im_class <class '__main__.C'>
This possibility is gone in Python 3::
>>> C.f.im_class Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'function' object has no attribute 'im_class' >>> dir(C.f) ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
This limits again the introspection capabilities available to the user. It can produce actual issues when porting software to Python 3, for example Twisted Core where the issue of introspecting method objects came up several times. It also limits pickling support [1]_.
Proposal ========
This PEP proposes the addition of a ``__qname__`` attribute to functions and classes. For top-level functions and classes, the ``__qname__`` attribute is equal to the ``__name__`` attribute. For nested classed, methods, and nested functions, the ``__qname__`` attribute contains a dotted path leading to the object from the module top-level.
The repr() and str() of functions and classes is modified to use ``__qname__`` rather than ``__name__``.
Example with nested classes ---------------------------
class C:
... def f(): pass ... class D: ... def g(): pass ...
C.__qname__
'C'
C.f.__qname__
'C.f'
C.D.__qname__
'C.D'
C.D.g.__qname__
'C.D.g'
Example with nested functions -----------------------------
def f():
... def g(): pass ... return g ...
f.__qname__
'f'
f().__qname__
'f.g'
Limitations ===========
With nested functions (and classes defined inside functions), the dotted path will not be walkable programmatically as a function's namespace is not available from the outside. It will still be more helpful to the human reader than the bare ``__name__``.
As the ``__name__`` attribute, the ``__qname__`` attribute is computed statically and it will not automatically follow rebinding.
References ==========
.. [1] "pickle should support methods": http://bugs.python.org/issue9276
Copyright =========
This document has been placed in the public domain.
.. Local Variables: mode: indented-text indent-tabs-mode: nil sentence-end-double-space: t fill-column: 70 coding: utf-8 End:

On 29/10/2011 23:18, Antoine Pitrou wrote:
Proposal
This PEP proposes the addition of a ``__qname__`` attribute to functions and classes. For top-level functions and classes, the ``__qname__`` attribute is equal to the ``__name__`` attribute. For nested classed, methods, and nested functions, the ``__qname__`` attribute contains a dotted path leading to the object from the module top-level.
The repr() and str() of functions and classes is modified to use ``__qname__`` rather than ``__name__``.
[snip] The only criticism I have is that I think I'd prefer it if it were called something more like "__qualname__".

On Sun, Oct 30, 2011 at 8:18 AM, Antoine Pitrou solipsis@pitrou.net wrote:
Hello,
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)).
Indeed (and I believe this should make the next version of the module aliasing PEP substantially shorter!).
Proposal
This PEP proposes the addition of a ``__qname__`` attribute to functions and classes. For top-level functions and classes, the ``__qname__`` attribute is equal to the ``__name__`` attribute. For nested classed, methods, and nested functions, the ``__qname__`` attribute contains a dotted path leading to the object from the module top-level.
I like '__qname__'. While I'm sympathetic to the suggestion of the more explicit '__qualname__', I actually prefer the idea of adding "qname" as an official shorthand for "qualified name" in the glossary.
Example with nested classes
class C:
... def f(): pass ... class D: ... def g(): pass ...
C.__qname__
'C'
C.f.__qname__
'C.f'
C.D.__qname__
'C.D'
C.D.g.__qname__
'C.D.g'
Example with nested functions
def f():
... def g(): pass ... return g ...
f.__qname__
'f'
f().__qname__
'f.g'
For nested functions, I suggest adding something to the qname to directly indicate that the scope is hidden. Adding parentheses to the name of the outer function would probably work:
f().g
Cheers, Nick.

On Sun, 30 Oct 2011 09:52:15 +1000 Nick Coghlan ncoghlan@gmail.com wrote:
Example with nested functions
def f():
... def g(): pass ... return g ...
f.__qname__
'f'
f().__qname__
'f.g'
For nested functions, I suggest adding something to the qname to directly indicate that the scope is hidden. Adding parentheses to the name of the outer function would probably work:
f().g
I don't know, I find the "()" a bit too smart. I'd like Guido's advice on the matter.
Regards
Antoine.

On Fri, Nov 4, 2011 at 12:38 PM, Antoine Pitrou solipsis@pitrou.net wrote:
On Sun, 30 Oct 2011 09:52:15 +1000 Nick Coghlan ncoghlan@gmail.com wrote:
Example with nested functions
def f():
... def g(): pass ... return g ...
f.__qname__
'f'
f().__qname__
'f.g'
For nested functions, I suggest adding something to the qname to directly indicate that the scope is hidden. Adding parentheses to the name of the outer function would probably work:
f().g
I don't know, I find the "()" a bit too smart. I'd like Guido's advice on the matter.
Hm. Both 'f.g' and 'f().g' for f().__qname__ are misleading, since both look like valid expressions but neither will actually retrieve the intended object. I'd be tempted to return something like '<local in f>.g' where 'f' would be f.__qname__. And yes, if f.__qname__ were '<local in xyzzy>.f', then f().__qname__ should be '<local in <local in xyzzy>.f>.g'.
Alternatively perhaps I could live with 'f.<locals>.g' and 'xyzzy.<locals>.f.<locals>.g'.
In either case, the use of <...> makes it plain that this should not be taken literally as an expression -- unlike the case of nested classes, where generally 'C.D.E' works to access E, if you have class C containing class D which contains class E.

On Fri, 4 Nov 2011 13:49:23 -0700 Guido van Rossum guido@python.org wrote:
Hm. Both 'f.g' and 'f().g' for f().__qname__ are misleading, since both look like valid expressions but neither will actually retrieve the intended object.
Agreed.
Alternatively perhaps I could live with 'f.<locals>.g' and 'xyzzy.<locals>.f.<locals>.g'.
Ah, thanks! I like this one.
Regards
Antoine.

On Sat, Nov 5, 2011 at 7:53 AM, Antoine Pitrou solipsis@pitrou.net wrote:
On Fri, 4 Nov 2011 13:49:23 -0700 Guido van Rossum guido@python.org wrote:
Alternatively perhaps I could live with 'f.<locals>.g' and 'xyzzy.<locals>.f.<locals>.g'.
Ah, thanks! I like this one.
Yep, I like that scheme, too.
Cheers, Nick.

Guido van Rossum dixit (2011-11-04, 13:49):
On Fri, Nov 4, 2011 at 12:38 PM, Antoine Pitrou solipsis@pitrou.net wrote:
On Sun, 30 Oct 2011 09:52:15 +1000 Nick Coghlan ncoghlan@gmail.com wrote:
[snip]
For nested functions, I suggest adding something to the qname to directly indicate that the scope is hidden. Adding parentheses to the name of the outer function would probably work:
f().g
I don't know, I find the "()" a bit too smart. I'd like Guido's advice on the matter.
Hm. Both 'f.g' and 'f().g' for f().__qname__ are misleading, since both look like valid expressions but neither will actually retrieve the intended object. I'd be tempted to return something like '<local in f>.g' where 'f' would be f.__qname__. And yes, if f.__qname__ were '<local in xyzzy>.f', then f().__qname__ should be '<local in <local in xyzzy>.f>.g'.
Alternatively perhaps I could live with 'f.<locals>.g' and 'xyzzy.<locals>.f.<locals>.g'.
And what about:
<f locals>.g and <<xyzzy locals>.f locals>.g
Cheers. *j

On Fri, Nov 4, 2011 at 4:15 PM, Jan Kaliszewski zuo@chopin.edu.pl wrote:
Guido van Rossum dixit (2011-11-04, 13:49):
On Fri, Nov 4, 2011 at 12:38 PM, Antoine Pitrou solipsis@pitrou.net
wrote:
On Sun, 30 Oct 2011 09:52:15 +1000 Nick Coghlan ncoghlan@gmail.com wrote:
[snip]
For nested functions, I suggest adding something to the qname to directly indicate that the scope is hidden. Adding parentheses to the name of the outer function would probably work:
f().g
I don't know, I find the "()" a bit too smart. I'd like Guido's advice on the matter.
Hm. Both 'f.g' and 'f().g' for f().__qname__ are misleading, since both look like valid expressions but neither will actually retrieve the
intended
object. I'd be tempted to return something like '<local in f>.g' where
'f'
would be f.__qname__. And yes, if f.__qname__ were '<local in xyzzy>.f', then f().__qname__ should be '<local in <local in xyzzy>.f>.g'.
Alternatively perhaps I could live with 'f.<locals>.g' and 'xyzzy.<locals>.f.<locals>.g'.
And what about:
<f locals>.g and <<xyzzy locals>.f locals>.g
In the end I like the non-nested version better.

On Sat, 2011-11-05 at 00:15 +0100, Jan Kaliszewski wrote:
Guido van Rossum dixit (2011-11-04, 13:49):
On Fri, Nov 4, 2011 at 12:38 PM, Antoine Pitrou solipsis@pitrou.net wrote:
On Sun, 30 Oct 2011 09:52:15 +1000 Nick Coghlan ncoghlan@gmail.com wrote:
[snip]
For nested functions, I suggest adding something to the qname to directly indicate that the scope is hidden. Adding parentheses to the name of the outer function would probably work:
f().g
I don't know, I find the "()" a bit too smart. I'd like Guido's advice on the matter.
Hm. Both 'f.g' and 'f().g' for f().__qname__ are misleading, since both look like valid expressions but neither will actually retrieve the intended object. I'd be tempted to return something like '<local in f>.g' where 'f' would be f.__qname__. And yes, if f.__qname__ were '<local in xyzzy>.f', then f().__qname__ should be '<local in <local in xyzzy>.f>.g'.
Alternatively perhaps I could live with 'f.<locals>.g' and 'xyzzy.<locals>.f.<locals>.g'.
Too many dots I think.
And what about:
<f locals>.g
and <<xyzzy locals>.f locals>.g
Better, but I don't think you need to nest it to indicate that relationship. I would use a colon instead of a dot to indicate a namespace relationship.
f.g g is an attribute of f f[g] g is in the container f f:g g is in the namespace f
So I think I'd one of...
<xyzzy locals>:<f locals>:g xyzzy:f:g
A slice is used a completely different context.
Cheers, Ron

Ron Adam wrote:
Better, but I don't think you need to nest it to indicate that relationship. I would use a colon instead of a dot to indicate a namespace relationship.
f.g g is an attribute of f
Being an attribute of an object /is/ being in that object's namespace (functions being the obvious exception).
~Ethan~

On Oct 29, 2011 4:22 PM, "Antoine Pitrou" solipsis@pitrou.net wrote:
Hello,
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)).
I also have a draft implementation that's quite simple (http://hg.python.org/features/pep-3155).
Regards
Antoine.
PEP: 3155 Title: Qualified name for classes and functions Version: $Revision$ Last-Modified: $Date$ Author: Antoine Pitrou solipsis@pitrou.net Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 2011-10-29 Python-Version: 3.3 Post-History: Resolution: TBD
Rationale
Python's introspection facilities have long had poor support for nested classes. Given a class object, it is impossible to know whether it was defined inside another class or at module top-level; and, if the former, it is also impossible to know in which class it was defined. While use of nested classes is often considered poor style, the only reason for them to have second class introspection support is a lousy pun.
Python 3 adds insult to injury by dropping what was formerly known as unbound methods. In Python 2, given the following definition::
class C: def f(): pass
you can then walk up from the ``C.f`` object to its defining class::
C.f.im_class
<class '__main__.C'>
This possibility is gone in Python 3::
C.f.im_class
Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'function' object has no attribute 'im_class'
dir(C.f)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
This limits again the introspection capabilities available to the user. It can produce actual issues when porting software to Python 3, for
example
Twisted Core where the issue of introspecting method objects came up several times. It also limits pickling support [1]_.
Proposal
This PEP proposes the addition of a ``__qname__`` attribute to functions and classes. For top-level functions and classes, the ``__qname__`` attribute is equal to the ``__name__`` attribute. For nested classed, methods, and nested functions, the ``__qname__`` attribute contains a dotted path leading to the object from the module top-level.
The repr() and str() of functions and classes is modified to use
``__qname__``
rather than ``__name__``.
Example with nested classes
class C:
... def f(): pass ... class D: ... def g(): pass ...
C.__qname__
'C'
C.f.__qname__
'C.f'
C.D.__qname__
'C.D'
C.D.g.__qname__
'C.D.g'
Example with nested functions
def f():
... def g(): pass ... return g ...
f.__qname__
'f'
f().__qname__
'f.g'
Limitations
With nested functions (and classes defined inside functions), the dotted path will not be walkable programmatically as a function's namespace is
not
available from the outside. It will still be more helpful to the human reader than the bare ``__name__``.
If it helps, I have a patch that adds f_func to frame objects [1]. It points to the function that was called, so __qname__ could reference that function.
-eric
[1] see http://bugs.python.org/issue12857
As the ``__name__`` attribute, the ``__qname__`` attribute is computed statically and it will not automatically follow rebinding.
References
.. [1] "pickle should support methods": http://bugs.python.org/issue9276
Copyright
This document has been placed in the public domain.
.. Local Variables: mode: indented-text indent-tabs-mode: nil sentence-end-double-space: t fill-column: 70 coding: utf-8 End:
Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas

On Sun, 30 Oct 2011 00:13:02 -0600 Eric Snow ericsnowcurrently@gmail.com wrote:
If it helps, I have a patch that adds f_func to frame objects [1]. It points to the function that was called, so __qname__ could reference that function.
Perhaps, although my current implementation uses a bit of code in the compiler to precompute (most of) the __qname__ attribute.
Regards
Antoine.

Antoine Pitrou solipsis-xNDA5Wrcr86sTnJN9+BGXg@public.gmane.org writes:
This PEP proposes the addition of a ``__qname__`` attribute to functions and classes. For top-level functions and classes, the ``__qname__`` attribute is equal to the ``__name__`` attribute. For nested classed, methods, and nested functions, the ``__qname__`` attribute contains a dotted path leading to the object from the module top-level.
Did you consider making it an array of the actual class/function objects instead of a string? It seems to me that going from the actual objects to the string representation is much easier than having to go the other way around.
Best,
-Nikolaus

On Sun, 30 Oct 2011 16:41:42 -0400 Nikolaus Rath Nikolaus@rath.org wrote:
Antoine Pitrou solipsis@pitrou.net writes:
This PEP proposes the addition of a ``__qname__`` attribute to functions and classes. For top-level functions and classes, the ``__qname__`` attribute is equal to the ``__name__`` attribute. For nested classed, methods, and nested functions, the ``__qname__`` attribute contains a dotted path leading to the object from the module top-level.
Did you consider making it an array of the actual class/function objects instead of a string? It seems to me that going from the actual objects to the string representation is much easier than having to go the other way around.
That would add a ton of references and reference cycles, keeping objects alive while they really shouldn't, and making cleanup in the face of __del__ methods much more problematic than it already is.
Regards
Antoine.

How meaningful are the extra two slots for every function or class object?
Have you done benchmarks like the Unicode Changes PEP has?
-jJ

On Mon, 31 Oct 2011 10:17:14 -0400 Jim Jewett jimjjewett@gmail.com wrote:
How meaningful are the extra two slots for every function or class object?
It's only one extra slot per function or class. It represents a 6% increase for functions, and a 1% increase for classes (not counting the space taken by the __qname__ string itself, but it will be usually be shared amongst many objects).
Have you done benchmarks like the Unicode Changes PEP has?
I don't expect it to have any interesting impact. What benchmarks do you have any mind?
Regards
Antoine.

On Mon, Oct 31, 2011 at 10:33 AM, Antoine Pitrou solipsis@pitrou.net wrote:
On Mon, 31 Oct 2011 10:17:14 -0400 Jim Jewett jimjjewett@gmail.com wrote:
How meaningful are the extra two slots for every function or class object?
It's only one extra slot per function or class.
OK; I was thinking of both the object qname and its module's qname, but I agree that they are separable.
Have you done benchmarks like the Unicode Changes PEP has?
I don't expect it to have any interesting impact. What benchmarks do you have any mind?
I would personally be satisfied with just timing the regression suite before and after, though others (Unladen Swallow?) may have more representative workloads.
My biggest concern is that any memory increase (let alone 6%) may matter if it forces the use of extra cache lines.
-jJ

Have you done benchmarks like the Unicode Changes PEP has?
I don't expect it to have any interesting impact. What benchmarks do you have any mind?
I would personally be satisfied with just timing the regression suite before and after, though others (Unladen Swallow?) may have more representative workloads.
My biggest concern is that any memory increase (let alone 6%) may matter if it forces the use of extra cache lines.
I've just timed running the test suite (in non-debug mode) and the result (user CPU time) is not significantly different: 3m5s without the patch, 3m7s with it.
pybench also shows similar results. Without patch:
Test minimum average operation overhead ------------------------------------------------------------------------------- BuiltinFunctionCalls: 59ms 60ms 0.12us 0.164ms ComplexPythonFunctionCalls: 60ms 62ms 0.31us 0.275ms PythonFunctionCalls: 55ms 56ms 0.17us 0.165ms PythonMethodCalls: 74ms 74ms 0.33us 0.099ms ------------------------------------------------------------------------------- Totals: 248ms 252ms
With patch:
Test minimum average operation overhead ------------------------------------------------------------------------------- BuiltinFunctionCalls: 59ms 61ms 0.12us 0.163ms ComplexPythonFunctionCalls: 59ms 60ms 0.30us 0.273ms PythonFunctionCalls: 55ms 55ms 0.17us 0.164ms PythonMethodCalls: 77ms 78ms 0.35us 0.099ms ------------------------------------------------------------------------------- Totals: 251ms 254ms
Regards
Antoine.

On Mon, Oct 31, 2011 at 3:54 PM, Antoine Pitrou solipsis@pitrou.net wrote:
I would personally be satisfied with just timing the regression suite before and after, though others (Unladen Swallow?) may have more representative workloads.
...
I've just timed running the test suite (in non-debug mode) and the result (user CPU time) is not significantly different: 3m5s without the patch, 3m7s with it.
pybench also shows similar results.
Great; I would agree that the costs appear minimal; please include these results in the PEP for posterity, whatever the decision.
-jJ

On Tue, Nov 1, 2011 at 5:37 AM, Jim Jewett jimjjewett@gmail.com wrote:
On Mon, Oct 31, 2011 at 10:33 AM, Antoine Pitrou solipsis@pitrou.net wrote:
On Mon, 31 Oct 2011 10:17:14 -0400 Jim Jewett jimjjewett@gmail.com wrote:
How meaningful are the extra two slots for every function or class object?
It's only one extra slot per function or class.
OK; I was thinking of both the object qname and its module's qname, but I agree that they are separable.
Yeah, adding __qmodule__ is part of the module aliasing PEP (395) rather than this one.
It's technically not needed for functions (you could do f.func_globals["__qname__"] instead), but classes definitely need it in order to kill off the corner cases that currently force developers to choose between breaking serialisation and breaking pickling.
The main differences between __qname__ and __qmodule__ and the Unicode changes are that there are a *lot* of small strings in any Python application, and an additional pointer or two can make a reasonably significant difference to their size, but classes and functions are already relatively complex objects.
On trunk:
def f(): pass
...
class C(): pass
...
import sys sys.getsizeof("")
60
sys.getsizeof(f)
136
sys.getsizeof(C)
832
(And those numbers don't even take into account the size of automatically created subobjects like C.__dict__, f.__dict__, f.__code__, etc)
Cheers, Nick.

On Sun, Oct 30, 2011 at 00:18, Antoine Pitrou solipsis@pitrou.net wrote:
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)).
Are these names relative or fully absolute? I.e. I've had problems in the past with unpickling objects that were pickled from a module that was imported using a relative import. Would it be possible to define the qname such that the full path to the name, starting from a sys.path level down, is always used?
Cheers,
Dirkjan

On Mon, 31 Oct 2011 16:42:00 +0100 Dirkjan Ochtman dirkjan@ochtman.nl wrote:
On Sun, Oct 30, 2011 at 00:18, Antoine Pitrou solipsis@pitrou.net wrote:
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)).
Are these names relative or fully absolute? I.e. I've had problems in the past with unpickling objects that were pickled from a module that was imported using a relative import. Would it be possible to define the qname such that the full path to the name, starting from a sys.path level down, is always used?
The __qname__, by design, doesn't include any module name. To get the "full path", you still have to add in the __module__ attribute. Solving the problems with relative imports (I'm not sure what they are) is another problem which Nick is apparently tackling (?).
Regards
Antoine.

On Tue, Nov 1, 2011 at 1:50 AM, Antoine Pitrou solipsis@pitrou.net wrote:
On Mon, 31 Oct 2011 16:42:00 +0100 Dirkjan Ochtman dirkjan@ochtman.nl wrote:
On Sun, Oct 30, 2011 at 00:18, Antoine Pitrou solipsis@pitrou.net wrote:
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)).
Are these names relative or fully absolute? I.e. I've had problems in the past with unpickling objects that were pickled from a module that was imported using a relative import. Would it be possible to define the qname such that the full path to the name, starting from a sys.path level down, is always used?
The __qname__, by design, doesn't include any module name. To get the "full path", you still have to add in the __module__ attribute. Solving the problems with relative imports (I'm not sure what they are) is another problem which Nick is apparently tackling (?).
PEP 395 (Module Aliasing) is indeed intended to handle the module naming half of the serialisation issues.
However, relative imports shouldn't cause pickling problems - the import machinery works out the full name and stores that in __name__ (if there is any case in 3.x where it doesn't, then that's a bug).
That said, *applications* (such as Django, up to and including v1.3) can corrupt __name__ values by placing package (or subpackage) directories directly on sys.path. Once an application does that, they run the risk of getting multiple copies of the same module with different __name__ values, and serialisation will then depend on exactly which version of the module was used to create the instances being serialised.
Django, at least, is going to stop doing that by default in 1.4, but it's still one of the easiest ways for an application to get itself in trouble when it comes to serialisation. And, because it's an outright application bug, there isn't really a lot the interpreter can do to correct for it (or even warn about it - however, see http://bugs.python.org/issue13306).
You can also get a similar effect in 2.x by running a file directly from a package when that file uses implicit relative imports. In that case, it's really the implicit relative imports that are at fault, though - there's a reason we killed them in Python 3. If you try the same thing with explicit relative imports, you at least get a noisy failure (and, with the module aliasing PEP, the plan is to just "Do The Right Thing" instead of complaining - there's no ambiguity in what the user is asking for, we just need to do some additional coding to actually make it happen).
Cheers, Nick.

class C:
... def f(): pass ... class D: ... def g(): pass ...
C.D.__qname__
'C.D'
C.D.g.__qname__
'C.D.g'
def f():
... def g(): pass ... return g ...
f().__qname__
'f.g'
Oh, +1 just for these examples.
It would help debugging if the __repr__ method of common objects are patched to use it.
Victor

Hi,
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)). [snip PEP]
+1.
For nested functions, I too think that 'f.<locals>.g' has too many dots; I like '<local in f>.g' or '<f locals>.g'.
polka-dots-ly yours

On Sat, Nov 5, 2011 at 10:32 AM, Éric Araujo merwok@netwok.org wrote:
Hi,
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)). [snip PEP]
+1.
For nested functions, I too think that 'f.<locals>.g' has too many dots; I like '<local in f>.g' or '<f locals>.g'.
I like it too but don't think it's too many dots.
The function from which the locals came _could_ be rolled into the brackets. However, in the context of some object (like the class X to which f belongs), 'X.f.<locals of f>.g' makes more sense in that case than 'X.<locals of f>.g', since the locals is related to f and not X. But, then the f is sort of redundant, so you go back to 'X.f.<locals>.g', and '<locals>' is still sort of unambiguous.
The disconnect is that <locals> is an externally anonymous namespace resulting from a call, rather than bound to any external namespace (like an object). Perhaps it would be appropriate to use 'X.f().<locals>.g' to make that clear.
-eric
polka-dots-ly yours _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas

On Sat, 2011-11-05 at 11:04 -0600, Eric Snow wrote:
On Sat, Nov 5, 2011 at 10:32 AM, Éric Araujo merwok@netwok.org wrote:
Hi,
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)). [snip PEP]
+1.
For nested functions, I too think that 'f.<locals>.g' has too many dots; I like '<local in f>.g' or '<f locals>.g'.
I like it too but don't think it's too many dots.
The function from which the locals came _could_ be rolled into the brackets. However, in the context of some object (like the class X to which f belongs), 'X.f.<locals of f>.g' makes more sense in that case than 'X.<locals of f>.g', since the locals is related to f and not X. But, then the f is sort of redundant, so you go back to 'X.f.<locals>.g', and '<locals>' is still sort of unambiguous.
The disconnect is that <locals> is an externally anonymous namespace resulting from a call, rather than bound to any external namespace (like an object). Perhaps it would be appropriate to use 'X.f().<locals>.g' to make that clear.
I think if you consider locals in f as an implementation detail of f's name space rather than a sub item of f, it's not as confusing. It's better to think of locals as being part of f, rather than in f. That is why <f locals> makes more sense than f.<locals>. For example locals is in f's frame object, so if you follow that reasoning you get. f.<frame>.<locals>, but I don't think we need all that.
Hmmm... I think it actually should be spelled...
f.<local g>
Following a pattern of...
x object x x.f f in object x x.f.<local g> local g in f in x
That's both clear and concise.
Cheers, Ron

I think you're all overthinking this. We want a notation that: 1. Makes it clear attribute access won't work 2. Indicates where the nested definition really lives 3. Gives a reasonable error message if you do try to evaluate it
"f.<locals>.g" ticks all those boxes, so it's fine.
-- Nick Coghlan (via Gmail on Android, so likely to be more terse than usual) On Nov 6, 2011 4:02 AM, "Ron Adam" ron3200@gmail.com wrote:
On Sat, 2011-11-05 at 11:04 -0600, Eric Snow wrote:
On Sat, Nov 5, 2011 at 10:32 AM, Éric Araujo merwok@netwok.org wrote:
Hi,
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)). [snip PEP]
+1.
For nested functions, I too think that 'f.<locals>.g' has too many
dots;
I like '<local in f>.g' or '<f locals>.g'.
I like it too but don't think it's too many dots.
The function from which the locals came _could_ be rolled into the brackets. However, in the context of some object (like the class X to which f belongs), 'X.f.<locals of f>.g' makes more sense in that case than 'X.<locals of f>.g', since the locals is related to f and not X. But, then the f is sort of redundant, so you go back to 'X.f.<locals>.g', and '<locals>' is still sort of unambiguous.
The disconnect is that <locals> is an externally anonymous namespace resulting from a call, rather than bound to any external namespace (like an object). Perhaps it would be appropriate to use 'X.f().<locals>.g' to make that clear.
I think if you consider locals in f as an implementation detail of f's name space rather than a sub item of f, it's not as confusing. It's better to think of locals as being part of f, rather than in f. That is why <f locals> makes more sense than f.<locals>. For example locals is in f's frame object, so if you follow that reasoning you get. f.<frame>.<locals>, but I don't think we need all that.
Hmmm... I think it actually should be spelled...
f.<local g>
Following a pattern of...
x object x x.f f in object x x.f.<local g> local g in f in x
That's both clear and concise.
Cheers, Ron
Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas

On Sat, Nov 5, 2011 at 3:31 PM, Nick Coghlan ncoghlan@gmail.com wrote:
I think you're all overthinking this. We want a notation that:
- Makes it clear attribute access won't work
- Indicates where the nested definition really lives
- Gives a reasonable error message if you do try to evaluate it
"f.<locals>.g" ticks all those boxes, so it's fine.
+1. Let's stop the bikeshedding.

On Sat, 5 Nov 2011 18:37:14 -0700 Guido van Rossum guido@python.org wrote:
On Sat, Nov 5, 2011 at 3:31 PM, Nick Coghlan ncoghlan@gmail.com wrote:
I think you're all overthinking this. We want a notation that:
- Makes it clear attribute access won't work
- Indicates where the nested definition really lives
- Gives a reasonable error message if you do try to evaluate it
"f.<locals>.g" ticks all those boxes, so it's fine.
+1. Let's stop the bikeshedding.
I've now updated the PEP and the implementation for "f.<locals>.g" to be the __qname__ value in that case.
Regards
Antoine.

On Sat, Nov 5, 2011 at 9:01 PM, Ron Adam ron3200@gmail.com wrote:
On Sat, 2011-11-05 at 11:04 -0600, Eric Snow wrote:
On Sat, Nov 5, 2011 at 10:32 AM, Éric Araujo merwok@netwok.org wrote:
Hi,
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)). [snip PEP]
+1.
For nested functions, I too think that 'f.<locals>.g' has too many dots; I like '<local in f>.g' or '<f locals>.g'.
I like it too but don't think it's too many dots.
The function from which the locals came _could_ be rolled into the brackets. However, in the context of some object (like the class X to which f belongs), 'X.f.<locals of f>.g' makes more sense in that case than 'X.<locals of f>.g', since the locals is related to f and not X. But, then the f is sort of redundant, so you go back to 'X.f.<locals>.g', and '<locals>' is still sort of unambiguous.
The disconnect is that <locals> is an externally anonymous namespace resulting from a call, rather than bound to any external namespace (like an object). Perhaps it would be appropriate to use 'X.f().<locals>.g' to make that clear.
I think if you consider locals in f as an implementation detail of f's name space rather than a sub item of f, it's not as confusing. It's better to think of locals as being part of f, rather than in f. That is why <f locals> makes more sense than f.<locals>. For example locals is in f's frame object, so if you follow that reasoning you get. f.<frame>.<locals>, but I don't think we need all that.
Hmmm... I think it actually should be spelled...
f.<local g>
Following a pattern of...
x object x x.f f in object x x.f.<local g> local g in f in x
That's both clear and concise.
Cheers, Ron _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
May i bikeshed a bit more please?
+1 to Ron
1) C.f.<locals>.g 2) C.<f locals>.g 3) C.f.<local g> I think less verbose and confusing is variant 3

No, Guido already accepted the PEP with the existing spelling.
-- Nick Coghlan (via Gmail on Android, so likely to be more terse than usual) On Nov 28, 2011 7:34 AM, "Roman Evstifeev" someuniquename@gmail.com wrote:
On Sat, Nov 5, 2011 at 9:01 PM, Ron Adam ron3200@gmail.com wrote:
On Sat, 2011-11-05 at 11:04 -0600, Eric Snow wrote:
On Sat, Nov 5, 2011 at 10:32 AM, Éric Araujo merwok@netwok.org wrote:
Hi,
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself
:-)).
[snip PEP]
+1.
For nested functions, I too think that 'f.<locals>.g' has too many
dots;
I like '<local in f>.g' or '<f locals>.g'.
I like it too but don't think it's too many dots.
The function from which the locals came _could_ be rolled into the brackets. However, in the context of some object (like the class X to which f belongs), 'X.f.<locals of f>.g' makes more sense in that case than 'X.<locals of f>.g', since the locals is related to f and not X. But, then the f is sort of redundant, so you go back to 'X.f.<locals>.g', and '<locals>' is still sort of unambiguous.
The disconnect is that <locals> is an externally anonymous namespace resulting from a call, rather than bound to any external namespace (like an object). Perhaps it would be appropriate to use 'X.f().<locals>.g' to make that clear.
I think if you consider locals in f as an implementation detail of f's name space rather than a sub item of f, it's not as confusing. It's better to think of locals as being part of f, rather than in f. That is why <f locals> makes more sense than f.<locals>. For example locals is in f's frame object, so if you follow that reasoning you get. f.<frame>.<locals>, but I don't think we need all that.
Hmmm... I think it actually should be spelled...
f.<local g>
Following a pattern of...
x object x x.f f in object x x.f.<local g> local g in f in x
That's both clear and concise.
Cheers, Ron _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
May i bikeshed a bit more please?
+1 to Ron
- C.f.<locals>.g
- C.<f locals>.g
- C.f.<local g>
I think less verbose and confusing is variant 3 _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas

And, lest this becomes proof by authority, let me point out that the <f locals> and <local g> notations are inconsistent, since at other positions in tha actual name is between the dots (or at least has a dot or the end of the string on each side).
--Guido
On Sun, Nov 27, 2011 at 2:05 PM, Nick Coghlan ncoghlan@gmail.com wrote:
No, Guido already accepted the PEP with the existing spelling.
-- Nick Coghlan (via Gmail on Android, so likely to be more terse than usual)
On Nov 28, 2011 7:34 AM, "Roman Evstifeev" someuniquename@gmail.com wrote:
On Sat, Nov 5, 2011 at 9:01 PM, Ron Adam ron3200@gmail.com wrote:
On Sat, 2011-11-05 at 11:04 -0600, Eric Snow wrote:
On Sat, Nov 5, 2011 at 10:32 AM, Éric Araujo merwok@netwok.org wrote:
Hi,
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)). [snip PEP]
+1.
For nested functions, I too think that 'f.<locals>.g' has too many dots; I like '<local in f>.g' or '<f locals>.g'.
I like it too but don't think it's too many dots.
The function from which the locals came _could_ be rolled into the brackets. However, in the context of some object (like the class X to which f belongs), 'X.f.<locals of f>.g' makes more sense in that case than 'X.<locals of f>.g', since the locals is related to f and not X. But, then the f is sort of redundant, so you go back to 'X.f.<locals>.g', and '<locals>' is still sort of unambiguous.
The disconnect is that <locals> is an externally anonymous namespace resulting from a call, rather than bound to any external namespace (like an object). Perhaps it would be appropriate to use 'X.f().<locals>.g' to make that clear.
I think if you consider locals in f as an implementation detail of f's name space rather than a sub item of f, it's not as confusing. It's better to think of locals as being part of f, rather than in f. That is why <f locals> makes more sense than f.<locals>. For example locals is in f's frame object, so if you follow that reasoning you get. f.<frame>.<locals>, but I don't think we need all that.
Hmmm... I think it actually should be spelled...
f.<local g>
Following a pattern of...
x object x x.f f in object x x.f.<local g> local g in f in x
That's both clear and concise.
Cheers, Ron _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
May i bikeshed a bit more please?
+1 to Ron
- C.f.<locals>.g
- C.<f locals>.g
- C.f.<local g>
I think less verbose and confusing is variant 3 _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas

On Oct 30, 2011, at 12:18 AM, Antoine Pitrou wrote:
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)).
Nice PEP, and +1 for the concept (with Guido's preferred format). However, "qname" is pretty obscure and I only guessed what the "q" stood for by reading the title of the PEP.
It seems to me that this attribute represents the dotted path from module globals to the object. You have to be careful not to confuse this with a file system path, so something like __dotted_name__, __dotted_path__, or __full_name__ perhaps. I don't much care, but I do think cryptic abbreviations should be avoided.
Cheers, -Barry

Le 07/11/2011 16:34, Barry Warsaw a écrit :
Nice PEP, and +1 for the concept (with Guido's preferred format). However, "qname" is pretty obscure and I only guessed what the "q" stood for by reading the title of the PEP.
OTOH, qname will be easily found in search engine (one of my griefs with the “packaging” module name).
It seems to me that this attribute represents the dotted path from module globals to the object. You have to be careful not to confuse this with a file system path, so something like __dotted_name__, __dotted_path__, or __full_name__ perhaps. I don't much care, but I do think cryptic abbreviations should be avoided.
-1 on these propositions: A dotted name or path includes the module name for me (or for things like packaging.util.resolve_name). I’m less affirmative about “full name”; it could mean “full name in one module”, so that __module__ + __fullname__ == the fully qualified name. This terminology is not terrific: I don’t think it would be good to have a distinction between “full name” (a.b) and “fully qualified name” (module.a.b). I think “qualified name” and “fully qualified name” are better terms: “qualified” has IMO less assumptions than full (you ask yourself “in what way is it qualified?” and go to the docs, instead of thinking “ah, it’s the full name including the module” or “ah, it’s like __name__ but better, and without the module”), and “fully qualified” builds on “qualified”.
(I’m trying to be constructive, not bikeshedding; tell me if I fail.)
__qualname__ is less cryptic and not too long; __qualifiedname__ is even less cryptic.
Cheers

On Nov 07, 2011, at 05:19 PM, Éric Araujo wrote:
OTOH, qname will be easily found in search engine (one of my griefs with the “packaging” module name).
Are you sure about that? I.e. have you tried it?
-1 on these propositions: A dotted name or path includes the module name for me (or for things like packaging.util.resolve_name). I’m less affirmative about “full name”; it could mean “full name in one module”, so that __module__ + __fullname__ == the fully qualified name. This terminology is not terrific: I don’t think it would be good to have a distinction between “full name” (a.b) and “fully qualified name” (module.a.b). I think “qualified name” and “fully qualified name” are better terms: “qualified” has IMO less assumptions than full (you ask yourself “in what way is it qualified?” and go to the docs, instead of thinking “ah, it’s the full name including the module” or “ah, it’s like __name__ but better, and without the module”), and “fully qualified” builds on “qualified”.
(I’m trying to be constructive, not bikeshedding; tell me if I fail.)
__qualname__ is less cryptic and not too long; __qualifiedname__ is even less cryptic.
"scoped" could also be used instead of "qualified".
-Barry

On Mon, 7 Nov 2011 11:25:53 -0500 Barry Warsaw barry@python.org wrote:
On Nov 07, 2011, at 05:19 PM, Éric Araujo wrote:
OTOH, qname will be easily found in search engine (one of my griefs with the “packaging” module name).
Are you sure about that? I.e. have you tried it?
-1 on these propositions: A dotted name or path includes the module name for me (or for things like packaging.util.resolve_name). I’m less affirmative about “full name”; it could mean “full name in one module”, so that __module__ + __fullname__ == the fully qualified name. This terminology is not terrific: I don’t think it would be good to have a distinction between “full name” (a.b) and “fully qualified name” (module.a.b). I think “qualified name” and “fully qualified name” are better terms: “qualified” has IMO less assumptions than full (you ask yourself “in what way is it qualified?” and go to the docs, instead of thinking “ah, it’s the full name including the module” or “ah, it’s like __name__ but better, and without the module”), and “fully qualified” builds on “qualified”.
(I’m trying to be constructive, not bikeshedding; tell me if I fail.)
__qualname__ is less cryptic and not too long; __qualifiedname__ is even less cryptic.
"scoped" could also be used instead of "qualified".
How about __sname__? Ok, sorry :-)
Antoine.

Le 07/11/2011 17:25, Barry Warsaw a écrit :
On Nov 07, 2011, at 05:19 PM, Éric Araujo wrote:
OTOH, qname will be easily found in search engine
Are you sure about that? I.e. have you tried it?
I did, and it made me remember why I didn’t find “qname” cryptic: It is used by XML specs (Antoine, you could mention that in the PEP). Top Google results for “python qname” are XML-related.
More: http://en.wikipedia.org/wiki/QName http://en.wikipedia.org/wiki/Fully_qualified_name
(#include <disclaimer about wikipedia not being authoritative>)
"scoped" could also be used instead of "qualified".
You truly are a great name generator! +1 to either.
Cheers

Éric Araujo dixit (2011-11-07, 18:00):
Le 07/11/2011 17:25, Barry Warsaw a écrit :
On Nov 07, 2011, at 05:19 PM, Éric Araujo wrote:
OTOH, qname will be easily found in search engine
Are you sure about that? I.e. have you tried it?
I did, and it made me remember why I didn’t find “qname” cryptic: It is used by XML specs (Antoine, you could mention that in the PEP). Top Google results for “python qname” are XML-related.
More: http://en.wikipedia.org/wiki/QName http://en.wikipedia.org/wiki/Fully_qualified_name
(#include <disclaimer about wikipedia not being authoritative>)
"scoped" could also be used instead of "qualified".
You truly are a great name generator! +1 to either.
But without the underscore in the middle, please. We have __getattribute__ and __deepcopy__, not __get_attribute__ and __deep_copy__.
Cheers. *j

+1 qualname On Nov 8, 2011 8:48 AM, "Jan Kaliszewski" zuo@chopin.edu.pl wrote:
Éric Araujo dixit (2011-11-07, 18:00):
Le 07/11/2011 17:25, Barry Warsaw a écrit :
On Nov 07, 2011, at 05:19 PM, Éric Araujo wrote:
OTOH, qname will be easily found in search engine
Are you sure about that? I.e. have you tried it?
I did, and it made me remember why I didn’t find “qname” cryptic: It is used by XML specs (Antoine, you could mention that in the PEP). Top Google results for “python qname” are XML-related.
More: http://en.wikipedia.org/wiki/QName http://en.wikipedia.org/wiki/Fully_qualified_name
(#include <disclaimer about wikipedia not being authoritative>)
"scoped" could also be used instead of "qualified".
You truly are a great name generator! +1 to either.
But without the underscore in the middle, please. We have __getattribute__ and __deepcopy__, not __get_attribute__ and __deep_copy__.
Cheers. *j
Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas

On Tue, Nov 8, 2011 at 1:34 AM, Barry Warsaw barry@python.org wrote:
Nice PEP, and +1 for the concept (with Guido's preferred format). However, "qname" is pretty obscure and I only guessed what the "q" stood for by reading the title of the PEP.
It seems to me that this attribute represents the dotted path from module globals to the object. You have to be careful not to confuse this with a file system path, so something like __dotted_name__, __dotted_path__, or __full_name__ perhaps. I don't much care, but I do think cryptic abbreviations should be avoided.
For both this PEP and PEP 395 (module aliasing), we need a new term for a name that is "usually the same as __name__, but different in some cases where __name__ lacks necessary detail".
"qualified name" meets that criteria in both cases by covering all situations where __name__ underspecifies things. For classes and functions, __name__ leaves out the nesting information, so you can't reliable locate the definition based solely on __module__ and __name__. In the case of modules, we occasionally alter __name__ for other purposes (such as indicating the main module or to ensure objects get serialised with the correct module information when the file layout doesn't match the nominal module layout). The new qualified names will address all those cases without causing backwards compatibility issues for existing uses of __name__. Hence, -1 on terms other than "qualified", because they don't fit the module aliasing use case (which involves name that are neither scoped, nor necessarily dotted) and would require me to come up with yet another term for what is essentially the same concept.
The question then is whether or not to introduce "qname" as an officially documented abbreviation for "qualified name". And to that I say, "Hell, yes".
1. "qualifiedname" and "qualified_name" is just too damn long. I want an abbreviation. 2. "qualname" is too hard to say 3. People are going to come up with an abbreviation anyway, so we may as well make it an official one so we get to benefit as well
Being able to talk about "names and qnames" without ambiguity will make all of the affected code much easier to update and discuss than if we insist on using the full "qualified name" term every time.
Cheers, Nick.

On Nov 8, 11:16 am, Nick Coghlan ncogh...@gmail.com wrote:
For both this PEP and PEP 395 (module aliasing), we need a new term for a name that is "usually the same as __name__, but different in some cases where __name__ lacks necessary detail".
__aka__ ? :)

In general, one problem with abbreviations is that they are more difficult for non-native English speakers to understand and use. I've often heard such complaints from acquaintances for whom English is not their primary language. The other problem is that while *you* know what the 'q' stands for because you derived it from the underlying concept, someone who stumbles over it in the opposite direction will not know what it means. Maybe they'll search for it, but otherwise, it'll just be a meaningless combination of characters.
Python has always valued readability over writing convenience, and I think this is one of Guido's founding brilliant insights: code is read far more often then it is written. And yet, he managed to find elegant ways of expressing code clearly without being overly verbose.
For these reasons, I strongly believe that this attribute should not be abbreviated.
If the spelled out name is too long, find another one that conveys the same information in fewer characters. Several have been proposed and it's not hard to find others. E.g. __name_details__.
(I personally do not have a problem with underscores separating the words. Again, it makes it more clear, where as mashwords can be difficult to scan.)
Cheers, -Barry

On 08/11/2011 10:55 AM, Barry Warsaw wrote:
If the spelled out name is too long, find another one that conveys the same information in fewer characters. Several have been proposed and it's not hard to find others. E.g. __name_details__.
Sorry I haven't been paying attention to this thread, but has __fullname__ been considered?
Cheers,
Matt

Yeah, although I forget exactly when. The problem with it is that it is wrong (since the full name would include the module info)
-- Nick Coghlan (via Gmail on Android, so likely to be more terse than usual) On Nov 9, 2011 2:00 AM, "Matt Chaput" matt@whoosh.ca wrote:
On 08/11/2011 10:55 AM, Barry Warsaw wrote:
If the spelled out name is too long, find another one that conveys the same information in fewer characters. Several have been proposed and it's not hard to find others. E.g. __name_details__.
Sorry I haven't been paying attention to this thread, but has __fullname__ been considered?
Cheers,
Matt
______________________________**_________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/**mailman/listinfo/python-ideashttp://mail.python.org/mailman/listinfo/python-ideas

On Tue, 8 Nov 2011 10:55:40 -0500 Barry Warsaw barry@python.org wrote:
In general, one problem with abbreviations is that they are more difficult for non-native English speakers to understand and use. I've often heard such complaints from acquaintances for whom English is not their primary language. The other problem is that while *you* know what the 'q' stands for because you derived it from the underlying concept, someone who stumbles over it in the opposite direction will not know what it means. Maybe they'll search for it, but otherwise, it'll just be a meaningless combination of characters.
Python has always valued readability over writing convenience, and I think this is one of Guido's founding brilliant insights: code is read far more often then it is written. And yet, he managed to find elegant ways of expressing code clearly without being overly verbose.
For these reasons, I strongly believe that this attribute should not be abbreviated.
If the spelled out name is too long, find another one that conveys the same information in fewer characters. Several have been proposed and it's not hard to find others. E.g. __name_details__.
If we go that way, I'd still prefer __qualname__ (but I'm fine with __qname__ :-)).
Regards
Antoine.

On 11/8/11, Barry Warsaw barry@python.org wrote:
... one problem with abbreviations is that they are more difficult for non-native English speakers to understand and use.
qname seems to be well established for XML. Do you fear that the q doesn't look enough like a prefix, and they won't recognize it as a type of name, or only that they won't know what makes this type of name special?
Python has always valued readability over writing convenience, and I think this is one of Guido's founding brilliant insights: code is read far more often then it is written. And yet, he managed to find elegant ways of expressing code clearly without being overly verbose.
Frankly, I wouldn't know precisely what a "qualified name" is, and I can only guess based on my painful experience with other systems -- of which XML is by far the least ugly. I'm not sure a standard abbreviation makes things any worse. ("Fully Qualified Name" isn't as bad, but clearly runs afoul of succinctness.)
-jJ

On Nov 09, 2011, at 02:32 PM, Jim Jewett wrote:
qname seems to be well established for XML. Do you fear that the q doesn't look enough like a prefix, and they won't recognize it as a type of name, or only that they won't know what makes this type of name special?
I think it will be easy to misread __qname__ as __name__ and it won't be obviously clear what the difference between them is.
Python has always valued readability over writing convenience, and I think this is one of Guido's founding brilliant insights: code is read far more often then it is written. And yet, he managed to find elegant ways of expressing code clearly without being overly verbose.
Frankly, I wouldn't know precisely what a "qualified name" is, and I can only guess based on my painful experience with other systems -- of which XML is by far the least ugly. I'm not sure a standard abbreviation makes things any worse. ("Fully Qualified Name" isn't as bad, but clearly runs afoul of succinctness.)
Isn't that a problem with the basic terminology then? If you don't know what a "qualified name" is you probably won't know what a "qname" is, and you definitely won't make that connection. I think that's more reason to find the right terminology and spell it out.
-Barry

On Thu, Nov 10, 2011 at 8:04 AM, Barry Warsaw barry@python.org wrote:
Isn't that a problem with the basic terminology then? If you don't know what a "qualified name" is you probably won't know what a "qname" is, and you definitely won't make that connection. I think that's more reason to find the right terminology and spell it out.
There may not *be* 'right terminology' for what a qname is going to be, since we're basically inventing the concept to cover some gaps in the meaning of __name__. I'm setting the mnemonic bar at "once you know what a Python qname is, is the name suggestive enough to let you remember it?", not at the much higher "if you encounter the Python qname term without knowing what it means, are you going to be able to guess correctly without looking it up?". I'm also considering the reverse problem of "if you encounter the Python qname term without knowing what it means, are you going to *think* you know what it means without looking it up and be incorrect?".
For me, it's that last point that rules out ideas like "full name" and "fully qualified" name - the proposed names deliberately *aren't* fully qualified in the class and function cases (since they still leave out the module information, storing that on a separate attribute).
For the former considerations, I think the differences between existing __name__ attributes and the new attributes are too subtle and obscure to ever allow completely intuitive terminology. For classes and functions, __name__ refers to the name given to the relevant constructor (either directly or syntactically). This is insufficient to correctly identify classes and functions that are not defined at the top level in their respective modules, so the new attribute addresses that. For modules, __name__ normally refers to the name that was used to import the module, *unless* it has been altered for some reason (either to mark the main module or else to redirect serialisation operations to a public API instead of an implementation module). The new attribute then allows those alterations of __name__ to take place without losing the information about which module was actually imported to create the module namespace.
"qname" and "qualified name" are nice, neutral terminology that suggest something closely related to "name" with being identical. In all proposed use cases, they preserve information that would otherwise have been lost.
That said, in earlier drafts of PEP 395 (module aliasing), I did suggest the term "implementation name". As in the current PEP, "__name__" would retain its current semantics, while "__impl_name__" would be what was actually imported when creating the module.
Logic that needed to figure out an objects full name would then look something like:
mod_name = obj.__module__ if mod_name == "__main__": mod_name = sys.modules[mod_name].__impl_name__ full_name = mod_name + "." + obj.__impl_name__
Introspection logic would use either or both, depending on the context (e.g. pydoc would likely favour using __name__, while inspect would prefer __impl_name__ for things like getsource()).
It seems to me that "implementation name" would work as a term for Antoine's PEP as well, since it's about providing enough information to locate the actual implementation of the class or function relative to the top level of the module.
The term "implementation name" is also a bit more suggestive of the intended purpose of these attributes than the completely neutral "qualified name".
That means my current order of naming preference is:
- "implementation name" & "__impl_name__" - "qualified name" & "__qname__" - "qualified name" & "__qualname__" - "qualified name" & "__qual_name__"
Cheers, Nick.

On Thu, 10 Nov 2011 10:24:18 +1000 Nick Coghlan ncoghlan@gmail.com wrote:
It seems to me that "implementation name" would work as a term for Antoine's PEP as well, since it's about providing enough information to locate the actual implementation of the class or function relative to the top level of the module.
I don't really follow this reasoning. There is no other object than the "actual implementation"; __name__ and __q[ual]name__ denote the same thing. "Implementation name" sounds like a misnomer to me.
If __qname__ is too elliptic, let's settle on __qualname__?
Regards
Antoine.

On Thu, Nov 10, 2011 at 11:00 AM, Antoine Pitrou solipsis@pitrou.net wrote:
On Thu, 10 Nov 2011 10:24:18 +1000 Nick Coghlan ncoghlan@gmail.com wrote:
It seems to me that "implementation name" would work as a term for Antoine's PEP as well, since it's about providing enough information to locate the actual implementation of the class or function relative to the top level of the module.
I don't really follow this reasoning. There is no other object than the "actual implementation"; __name__ and __q[ual]name__ denote the same thing. "Implementation name" sounds like a misnomer to me.
Yeah, on further reflection, I agree that the connotations suggesting a separate implementation object may be too strong for that to be a reasonable term. That's probably why I dropped it in the first place.
If __qname__ is too elliptic, let's settle on __qualname__?
"q name" is easy to say, "qual name" is relatively hard to say - if we're going to abbreviate, it should be to something pronounceable. I'd say try to summarise this naming discussion into the PEP, but otherwise stick to the "qualified name" and "__qname__" proposal (unless/until Guido says otherwise).
Cheers, Nick.

Le jeudi 10 novembre 2011 à 11:38 +1000, Nick Coghlan a écrit :
On Thu, Nov 10, 2011 at 11:00 AM, Antoine Pitrou solipsis@pitrou.net wrote:
On Thu, 10 Nov 2011 10:24:18 +1000 Nick Coghlan ncoghlan@gmail.com wrote:
It seems to me that "implementation name" would work as a term for Antoine's PEP as well, since it's about providing enough information to locate the actual implementation of the class or function relative to the top level of the module.
I don't really follow this reasoning. There is no other object than the "actual implementation"; __name__ and __q[ual]name__ denote the same thing. "Implementation name" sounds like a misnomer to me.
Yeah, on further reflection, I agree that the connotations suggesting a separate implementation object may be too strong for that to be a reasonable term. That's probably why I dropped it in the first place.
If __qname__ is too elliptic, let's settle on __qualname__?
"q name" is easy to say, "qual name" is relatively hard to say - if we're going to abbreviate, it should be to something pronounceable.
This must depend where you come from. I have no problem pronouncing "qualname" with a gross French accent, and I'm sure Victor would understand me :-)
Regards
Antoine.

On Thu, Nov 10, 2011 at 11:36 AM, Antoine Pitrou solipsis@pitrou.net wrote:
"q name" is easy to say, "qual name" is relatively hard to say - if we're going to abbreviate, it should be to something pronounceable.
This must depend where you come from. I have no problem pronouncing "qualname" with a gross French accent, and I'm sure Victor would understand me :-)
It isn't so much a matter of finding qualname hard to say, as finding qname really easy to say, so I don't actually mind if you do decide to change it in the PEP :)
Cheers, Nick.

On 11/9/11, Nick Coghlan ncoghlan@gmail.com wrote:
On Thu, Nov 10, 2011 at 8:04 AM, Barry Warsaw barry@python.org wrote:
Isn't that a problem with the basic terminology then? If you don't know what a "qualified name" is you probably won't know what a "qname" is, and you definitely won't make that connection. I think that's more reason to find the right terminology and spell it out.
I know that a "qualified name" is a special kind of name, and that if I have to worry about it, then I should expect subtle bugs with either false matches, false mismatches, or both.
I cannot imagine a more specific definition that is both true and sufficiently simple that I don't have to look it up.
But frankly, that seems to be true of the proposed names as well (usually but not always equal to __name__, often but not always sufficient to figure out where the object was defined, etc).
The only cognitive grief is about figuring out when I *do* need to use a qname instead of a regular name; I don't see a rule of thumb like "Handles user-generated strings" or "Multiple namespaces are being used".
There may not *be* 'right terminology' for what a qname is going to be, since we're basically inventing the concept to cover some gaps in the meaning of __name__.
And so I suspect there isn't a simple term. (There might be several simple terms that each describe some but not all of the use cases.)
I'm setting the mnemonic bar at "once you know what a Python qname is, is the name suggestive enough to let you remember it?", not at the much higher "if you encounter the Python qname term without knowing what it means, are you going to be able to guess correctly without looking it up?".
I would say that all of __qname__, __q_name__, __qualname__, __qualifiedname__, etc meet that bar, as do __extendedname__ or __impl_name__.
I'm also considering the reverse problem of "if you encounter the Python qname term without knowing what it means, are you going to *think* you know what it means without looking it up and be incorrect?".
I wouldn't, but I'm probably a bad judge on that.
-jJ

On Mon, 7 Nov 2011 10:34:24 -0500 Barry Warsaw barry@python.org wrote:
On Oct 30, 2011, at 12:18 AM, Antoine Pitrou wrote:
I would like to propose the following PEP for discussion and, if possible, acceptance. I think the proposal shouldn't be too controversial (I find it quite simple and straightforward myself :-)).
Nice PEP, and +1 for the concept (with Guido's preferred format). However, "qname" is pretty obscure and I only guessed what the "q" stood for by reading the title of the PEP.
It seems to me that this attribute represents the dotted path from module globals to the object. You have to be careful not to confuse this with a file system path, so something like __dotted_name__, __dotted_path__, or __full_name__ perhaps. I don't much care, but I do think cryptic abbreviations should be avoided.
Based on the feedback received, I've finally changed the attribute name to __qualname__. Pronunciation issues notwithstanding ;-), it is a reasonable compromise between explicitness and shortness/easy-of-typing.
Regards
Antoine.

On Sat, Nov 19, 2011 at 6:01 AM, Antoine Pitrou solipsis@pitrou.net wrote:
Based on the feedback received, I've finally changed the attribute name to __qualname__. Pronunciation issues notwithstanding ;-), it is a reasonable compromise between explicitness and shortness/easy-of-typing.
OK, I'll update PEP 395 accordingly (and given some discussions on import-sig this week, the title of that PEP is probably going to change to "Qualified names for modules")
I can't promise not to shorten it back to q-name if I ever have occasion to say it out loud, though :)
Cheers, Nick.
participants (18)
-
alex23
-
Antoine Pitrou
-
Barry Warsaw
-
Dirkjan Ochtman
-
Eric Snow
-
Ethan Furman
-
Guido van Rossum
-
Jan Kaliszewski
-
Jim Jewett
-
Matt Chaput
-
Matt Joiner
-
MRAB
-
Nick Coghlan
-
Nikolaus Rath
-
Roman Evstifeev
-
Ron Adam
-
Victor Stinner
-
Éric Araujo