__qualname__ in python 3.3

ISE Development isenntp at gmail.com
Sat Sep 6 13:09:56 EDT 2014


Peter Otten wrote:

> ISE Development wrote:
> 
>> Hi,
>> 
>> When a class is defined within a function, the class generation
>> function's '__qualname__' attrbute is not qualified a name.
>> 
>> For instance:
>> 
>>     def test():
>>         class T:
>>             def method(self):
>>                 pass
>>         t = T()
>>         t.method()
>> 
>> When tracing a call to 'test()' using 'sys.settrace()', extracting the
>> 'code' object from the frames of 'call' events and matching it to a
>> 'function' object (using 'gc.get_referrers()') results in the following:
>> 
>> 'code' object     'function' object
>> ----------------  ------------------------------------
>> co_name: test     __qualname__: test
>> co_name: T        __qualname__: T
>> co_name: method   __qualname__: test.<locals>.T.method
>> 
>> The second call corresponds to the class definition and not the call to
>> the constructor (which is in fact a call to 'object.__init__', a C
>> function hence not traced as a 'call' event - I checked this by
>> disassembling the code object).
>> 
>> I would expect the second call's '__qualname__' to be 'test.<locals>.T'.
>> Can this be considered a bug? If so, I'll open one.
> 
> I don't understand what you are doing, so I tried to reproduce the
> unqualified class name in 3.4 with the simpler approach of returning T:
> 
> Python 3.4.0 (default, Apr 11 2014, 13:05:11)
> [GCC 4.8.2] on linux
> Type "help", "copyright", "credits" or "license" for more information.
>>>> def test():
> ...     class T:
> ...         def method(self): pass
> ...     return T
> ...
>>>> T = test()
>>>> T.__qualname__
> 'test.<locals>.T'
>>>> T.method.__qualname__
> 'test.<locals>.T.method'
> 
> If you do it that way with 3.3 (I don't have it handy) do you still see
> T instead of test.<locals>.T?

Python 3.3 behaves in the same way in that case.

This following shows the behaviour I am referring to:

    import gc
    import sys
    import inspect

    def global_trace(frame,event,arg):
        if event == 'call':
            code = frame.f_code
            funcs = [obj for obj in gc.get_referrers(code)
                     if inspect.isfunction(obj)]
            if len(funcs) == 1:
                f = funcs[0]
                print(f.__qualname__)

    def test():
        class C:
            def method(self):
                self
        c = C()
        c.method()

    sys.settrace(global_trace)
    try:
        test()
    finally:
        sys.settrace(None)

which produces:

    test
    C
    test.<locals>.C.method




More information about the Python-list mailing list