Python中的Super详解

在这篇文章中,我们来介绍一下super。相信大部分人都是这样使用super的;

<code class="language-python"># 就是我有一个 class 比如说是 Male,然后继承另外一个 class 比如是 Person,然后我在这个 Male 也就是它的子类的 init 函数里面用 super().__init__() 来调用它父类的初识化函数
from objprint import op
class Person:
    def __init__(self, name):
        self.name = name
class Male(Person):
    def __init__(self, name):
        super().__init__(name)
        self.gender = "male"
m = Male('xiaoyang')
op(m)
# 输出:

​我们在常用super的时候,通常认为super是一个方法或者函数,但其​​实super是一个严肃的类,它是一个内置的名字,然后super()不调用函数,super()是创建一个超级对象

>>> type(super)

​虽然我们更常用的是括号内不带任何内容的super(),但是完整版的super应该有两个参数,第一个参数是一个类型,也就是一个类,第二个参数是一个类型或者是一个,其中第二个参数决定这个函数绑定到哪个类或类,第二个参数决定使用哪个mro,第一个参数决定从mro链上的哪个类开始查找。,例如;

from objprint import op
class Person:
    def __init__(self, name):
        self.name = name
class Male(Person):
    def __init__(self, name):
        # super().__init__(name)
        super(Male, self).__init__(name)
        self.gender = "male"
m = Male('xiaoyang')
op(m)
# 输出:

# 其实我们看刚才的 super().__init__(name) 它是等价于 super(Male, self).__init__(name) 的。

那么这个super(Male, self)就做了这样的事情。首先需要从self中获取mro,然后他会找到第一个,也就是mro中Male的位置,目前在Male的情况下,就是第一个(Male)。接下来他会开始寻找Male后面的类,然后它首先找到的是,然后看里面有没有这个函数,然后发现有这个函数,然后把这个绑定到self。这里可以理解为这个函数传入的self就是super中的self,也就是说。(self,name) 这行代码等价于 super(Male, self).(name) 这行代码。

为什么不直接使用 .(self,name) 有几个原因:

未来可能会改变基类的名称,甚至是继承方式。在这种情况下,如果您使用 super,则无需担心任何事情。它应该会自动跟随这个mro来找到正确的类,但是用这个如果要修改命名的类,它更容易导致错误。事实上,super 是动态的。他会根据self的mro进行搜索,传入的就是self。它是动态的,也就是说在同一个函数中。,我使用 super 来获得不同的类而不改变函数。

让我们看一下这个例子:

from objprint import op
class Animal:
    def __init__(self, age):
        self.age = age
class Person(Animal):
    def __init__(self, age, name):
        super().__init__(age)
        self.name = name
class Male(Person):
    def __init__(self,age, name):
        # super(Male, self).__init__(age, name) 
        super(Person, self).__init__(age, name) 
        self.gender = "male"
m = Male(18, 'xiaoyang')
op(m)

​如果你在Male super(Male, self).(age, name)中正常使用,那么它会正常初始化一切,它会访问这个,然后它会访问,最后这个就完成了Male。

那么如果你改成super(, self).(age, name),那么就会报错,因为我们在使用super(, self)的时候,self的mro链是Male然后,第一个参数It是因为是,所以他会从后面的类开始,也就是有一个函数,但是参数age只有一个,所以我们传入age名字的时候,是错误的,那么我们只需要设置它改为只传入一个年龄,如:super(, self).(age),也跳过。

总结一下 super 的两个参数分别是第一个类型和第二个类型或者分别决定的:

第一个仅确定从何处开始查找 mro 链

二是决定使用这个函数的对象和mro

super 不仅仅用在类中,它可以在任何地方使用,只要我给出第二个参数或类,从哪里开始寻找第一个参数,我可以使用它的功能,例如:

# 那这里的话就是从 m 这个 object 的 mro 上寻找 Male 后面开始的 __init__ 函数,这样实际上就找到了 Person 的 __init__ 函数,然后再用 Person 的 __init__ 函数对 m 这个 object 做初始化
from objprint import op
class Animal:
    def __init__(self, age):
        self.age = age
class Person(Animal):
    def __init__(self, age, name):
        super().__init__(age)
        self.name = name
class Male(Person):
    def __init__(self,age, name):
        super(Person, self).__init__(age)
        self.gender = "male"
m = Male(18, 'xiaoyang')
op(m)
print("----------------------")
super(Male, m).__init__(20, "xiaoyang")
op(m)
# 输出:

----------------------

© 版权声明
THE END
喜欢就支持一下吧
点赞8赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容