How is super() in Python 3 implemented?

后端 未结 2 1126
离开以前
离开以前 2020-11-29 10:26

I\'m wondering how is the new super in Python 3 implemented.

This question was born in my head after I have made a small example and I got a strange error. I\'m usin

2条回答
  •  时光取名叫无心
    2020-11-29 11:05

    TL;DR: This "empty __class__ cell" error will happen when the metaclass tries to call a method in the defined class (or instantiate it) before it is done with its __new__ and __init__,and the called method uses super. The error will also happen if one writes a call to super() in a function defined outside of a class body, and tries to add this method to an existing class and use it. (update: this behavior has been fixed in Python 3.6)

    Python 3 super makes an implicit reference to a "magic" __class__[*] name which behaves as a cell variable in the namespace of each class method.

    This variable is created automatically at the end of the class creation mechanism - i.e. whenever there is a class body in Python, the metaclass's __new__ and __init__ are run - when __init__ finishes, the __class__ cell is populated and made available to the class's methods.

    What is going on here, is that likely (I have not looked at all the code) in the PluginMeta initialization code, the class's __init__ is called, before the end of the metaclass __init__ - since one of the points of this metaclass is handling singletons - what is likely to happen is that the metaclass mechanism is instantiating the single-instance and populating __instance__ before returning from the metaclass' __init__. The implicit __class__ used by super does not exist at this point.

    Thus, referencing the superclass by the hardcoded name, as one had to do prior to super in Python2 will work - and is the best way to achieve what you want there.

    *- This is not the self.__class__ attribute of the instance, it is a __class__ variable actually available inside methods:

    class A:
       def a(self):
          print ("Instance's class: {}, "
                 "actual class where this line is coded: {}".format(
                     self.__class__, __class__))
    
    class B(A):
       pass
    

    And running this we have:

    >>> B().a()
    Instance's class: , actual class where this line is coded: 
    >>> 
    

    From the Python datamodel:

    __class__ is an implicit closure reference created by the compiler if any methods in a class body refer to either __class__ or super. This allows the zero argument form of super() to correctly identify the class being defined based on lexical scoping, while the class or instance that was used to make the current call is identified based on the first argument passed to the method.

    For more details, please check PEP 3135

提交回复
热议问题