137 lines
3.6 KiB
Plaintext
137 lines
3.6 KiB
Plaintext
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. 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
|
|
``__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.<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 ``__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:
|