【问题标题】:What does the super() point to on earth?super() 到底指向什么?
【发布时间】:2021-11-23 06:43:18
【问题描述】:

在帖子中,super() 被描述为:describe super()

super() looks at the next class in the MRO (method resolution order, accessed with cls.__mro__) to call the methods.   

有些材料甚至给出了更明确的定义: more clear definition on super()

def  super ( cls , inst ) : 
    mro = inst.__class__.mro( ) 
    return mro[mro.index( cls )  +  1 ]

创建一个多重继承类结构如下:

class state():
    def __init__(self):
        pass

class event():
    def __init__(self):
        pass

class happystate(state,event):
    def __init__(self):
        print(super())
        print(super(happystate,self))

mro 列表:

>>> happystate.__mro__
(<class '__main__.happystate'>, <class '__main__.state'>, <class '__main__.event'>, <class 'object'>)

happystate 类中的super() 将查看 MRO 中的下一个类,在此状态下是 state 类。

x=happystate()
<super: <class 'happystate'>, <happystate object>>
<super: <class 'happystate'>, <happystate object>>

为什么happystate类中的super()指向自身而不是MRO列表中的下一个类----state
如果super() 指向state,则输出应为:

x=happystate()
<super: <class 'state'>, <state object>>
<super: <class 'state'>, <state object>>

【问题讨论】:

  • 它不指向自己,super() 返回一个super object。注意前面的&lt;super:

标签: python-3.x multiple-inheritance super


【解决方案1】:

super() 返回 super 类的实例,该类跟踪 MRO 中的当前位置。在super 实例上调用方法时,super 在 MRO 中查找下一个类并调用该类上的方法。

也许这会有所帮助:

class state():
    def __init__(self):
        print('state.__init__')
        print(super())
        super().__init__()

class event():
    def __init__(self):
        print('event.__init__')
        print(super())
        super().__init__()

class happystate(state,event):
    def __init__(self):
        print('happystate.__init__')
        print(super())
        super().__init__()

print(happystate.mro())
x = happystate()

输出:

[<class '__main__.happystate'>, <class '__main__.state'>, <class '__main__.event'>, <class 'object'>]
happystate.__init__
<super: <class 'happystate'>, <happystate object>>  # currently in happystate of happystate object
state.__init__                                      # state is next
<super: <class 'state'>, <happystate object>>       # now in state of happystate object.
event.__init__                                      # event is next
<super: <class 'event'>, <happystate object>>       # now in event of happystate object

这也说明了在使用继承时,树中的所有类都需要使用super()。即使event 没有基类,在创建happystate 时,缺少super().__init__() 也永远不会调用state.__init__

【讨论】:

    【解决方案2】:

    它没有“指向”同一个类,super 是它自己的一个类:

    >>> super
    <class 'super'>
    
    >>> class happystate(state,event):
    ...     def __init__(self):
    ...         print(super(), type(super()))
    ... 
    >>> happystate()
    <super: <class 'happystate'>, <happystate object>> <class 'super'>
    

    所以你也可以在课外使用它:

    >>> super(happystate)
    <super: <class 'happystate'>, NULL>
    

    但是在类内部它有一些特殊的行为,所以让我们将它保存为实例变量,以便我们可以与它进行更多交互:

    >>> class happystate(state,event):
    ...     def __init__(self):
    ...         self.s = super()
    ... 
    >>> h = happystate()
    >>> h.s.__self_class__
    <class '__main__.happystate'>
    >>> h.s.__thisclass__
    <class '__main__.happystate'>                    # the class
    >>> h.s.__self__                      
    <__main__.happystate object at 0x7fa8a42642e0>   # the object of the class
    

    但这仍然不能告诉我们太多,所以让我们跳转at the docs for super

    返回一个代理对象,该对象将方法调用委托给该类型的父类或同级类。这对于访问已在类中覆盖的继承方法很有用。

    因此,归根结底,super 可以帮助您访问父类中的内容,而无需自己遍历 MRO,这意味着代码更简洁。让我们使用这些新发现的知识并稍微修改一下您的代码:

    class state():
        def __init__(self, x):
            print("state __init__", x)
            self.x = x
    
    class event():
        def __init__(self):
            print("event __init__")
    
    class happystate(state,event):
        def __init__(self):
            super(state, self).__init__()
            self.s = super()
    

    现在让我们尝试使用修改后的代码:

    >>> h = happystate()
    event __init__        # surprise! It doesn't call `state` 
                          # (or its super - `object`) but the
                          # next in the MRO for `happystate`: `event`!
    
    >>> h.s.__init__(3)   # calls state.__init__ (notice that we pass 1 argument)
    state __init__ 3
    >>> h.x               # state.__init__ received `h` as the `self` argument and updated it!
    3
    

    【讨论】:

      猜你喜欢
      • 2011-03-06
      • 2010-11-26
      • 2016-11-06
      • 1970-01-01
      • 1970-01-01
      • 2010-11-02
      • 2018-11-11
      • 2011-04-28
      相关资源
      最近更新 更多