super()函数的使用

Python·语法 2018-12-15 3131 字 20 浏览 点赞

说明

一些Python入门书并没有讲清楚super()函数应该怎么用,只在说继承知识点的时候顺便一笔带过。为此我糊涂了好久、好久……

继承

Python中的继承很容易实现,如下:

class A(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def greet(self):
        print("I'm A")

    def show(self):
        
        string = ("My name is {name}.\n"
                  "I'm {age}.".format(name=self.name, age=self.age))
        print(string)


class B(A):
    pass


if __name__ == "__main__":
    b = B("Guan", 18)
    b.greet()
    b.show()

# 输出:
I'm A
My name is Guan.
I'm 18.

所以继承父类的时候,super()函数并非必要

那什么时候确切的要用到super()呢?
答:欲求不满时。

使用super()

之所以需要“继承”,大部分原因是我们想要扩展基础类——需要派生类有更多的功能。当然了,如果只是额外增加一个“独立”功能,仍然用不到super()。如下:

class A(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def greet(self):
        print("I'm A")

    def show(self):
        
        string = ("My name is {name}.\n"
                  "I'm {age}.".format(name=self.name, age=self.age))
        print(string)


class B(A):
    # “独立”功能
    def cry(self):
        print("cry ...")


if __name__ == "__main__":
    b = B("Guan", 18)
    b.cry()

# 输出:
cry ... 

B类中的cry()是一个与A类完全无关的函数,所以直接定义就OK。但此时需求变了,我们需要B类的对象可以在自我介绍的时候先说hello。我们当然可以用如下方式重载show():

class B(A):
    def show(self):
        print("ya~hello~")
        string = ("My name is {name}.\n"
                  "I'm {age}.".format(name=self.name, age=self.age))
        print(string)

可这样做重复了A中的部分代码,很不“程序员”。所以super()出场了:

class B(A):
    def show(self):
        print("ya~hello~")
        super().show()

但python2中需要这样写:

class B(A):
    def show(self):
        print("ya~hello~")
        super(B, self).show()  # 需要传入自己的类名以及对象self

乍一看super()的意思是:获取父类。而super().show()就是调用父类的show()函数。是,也不是

真实的super()

super()获取的是MRO列表中下一个类。什么是MRO呢?这里不是重点,它有自己计算的方式,有兴趣可以自己找找资料。

示例:

class A(object):
    pass

class B(A):
    pass

if __name__ == "__main__":
    print(B.mro())

输出内容如下:
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

在MRO列表中,B的下一个类是A。所以在B类中的super(),代表A。这里刚好A是B的父类。也有不刚好的时候。

class A(object):
    def __init__(self):
        print("A")
        super().__init__()


class B(A):
    def __init__(self):
        print("B")
        super().__init__()


class C(A):
    def __init__(self):
        print("C")
        super().__init__()


class D(B, C):
    def __init__(self):
        print("D")
        super().__init__()


if __name__ == "__main__":
    d = D()
    print(D.mro())

# 输出:
D
B
C
A
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

注意ABCD的输出顺序。可以看到,B中调用super().__init__(),没有打印“A”,而是“C”,这是符合MRO列表顺序的。

总结

  • super()与父类没有直接关系
  • super()获取的是MRO列表中下一个类

感谢

参考个人博客 FunHacks
https://funhacks.net/explore-python/Class/super.html
参考慕课老师 bobby
https://www.bilibili.com/video/av28281876/?p=22



本文由 Guan 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论