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