Permalink
Cannot retrieve contributors at this time
172 lines (130 sloc)
4.9 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
peps/pep-3155.txt
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| PEP: 3155 | |
| Title: Qualified name for classes and functions | |
| Version: $Revision$ | |
| Last-Modified: $Date$ | |
| Author: Antoine Pitrou <solipsis@pitrou.net> | |
| Status: Final | |
| Type: Standards Track | |
| Content-Type: text/x-rst | |
| Created: 29-Oct-2011 | |
| Python-Version: 3.3 | |
| Post-History: | |
| Resolution: https://mail.python.org/pipermail/python-dev/2011-November/114545.html | |
| 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 ``__qualname__`` attribute to | |
| functions and classes. For top-level functions and classes, the | |
| ``__qualname__`` attribute is equal to the ``__name__`` attribute. For | |
| nested classes, methods, and nested functions, the ``__qualname__`` | |
| attribute contains a dotted path leading to the object from the module | |
| top-level. A function's local namespace is represented in that dotted | |
| path by a component named ``<locals>``. | |
| The repr() and str() of functions and classes is modified to use | |
| ``__qualname__`` rather than ``__name__``. | |
| Example with nested classes | |
| --------------------------- | |
| >>> class C: | |
| ... def f(): pass | |
| ... class D: | |
| ... def g(): pass | |
| ... | |
| >>> C.__qualname__ | |
| 'C' | |
| >>> C.f.__qualname__ | |
| 'C.f' | |
| >>> C.D.__qualname__ | |
| 'C.D' | |
| >>> C.D.g.__qualname__ | |
| 'C.D.g' | |
| Example with nested functions | |
| ----------------------------- | |
| >>> def f(): | |
| ... def g(): pass | |
| ... return g | |
| ... | |
| >>> f.__qualname__ | |
| 'f' | |
| >>> f().__qualname__ | |
| 'f.<locals>.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 ``__qualname__`` attribute is computed | |
| statically and it will not automatically follow rebinding. | |
| Discussion | |
| ========== | |
| Excluding the module name | |
| ------------------------- | |
| As ``__name__``, ``__qualname__`` doesn't include the module name. This | |
| makes it independent of module aliasing and rebinding, and also allows to | |
| compute it at compile time. | |
| Reviving unbound methods | |
| ------------------------ | |
| Reviving unbound methods would only solve a fraction of the problems this | |
| PEP solves, at a higher price (an additional object type and an additional | |
| indirection, rather than an additional attribute). | |
| Naming choice | |
| ============= | |
| "Qualified name" is the best approximation, as a short phrase, of what the | |
| additional attribute is about. It is not a "full name" or "fully qualified | |
| name" since it (deliberately) does not include the module name. Calling | |
| it a "path" would risk confusion with filesystem paths and the ``__file__`` | |
| attribute. | |
| The first proposal for the attribute name was to call it ``__qname__`` but | |
| many people (who are not aware of previous use of such jargon in e.g. the | |
| XML specification [2]_) found it obscure and non-obvious, which is why the | |
| slightly less short and more explicit ``__qualname__`` was finally chosen. | |
| References | |
| ========== | |
| .. [1] "pickle should support methods": | |
| http://bugs.python.org/issue9276 | |
| .. [2] "QName" entry in Wikipedia: | |
| http://en.wikipedia.org/wiki/QName | |
| 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: |