133 lines
3.5 KiB
Plaintext
133 lines
3.5 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.
|
||
|
|
||
|
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:
|