python中super的使用

2020-04-02  本文已影响0人  lifanxin

super的简单用法

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


class Son(Father):

    def __init__(self, name, age):
        # super(Son, self).__init__(name) 完整的调用方式,后面再详细说明
        super().__init__(name)    # 调用父类的初始化方法
        self.age = age            # 初始化本类参数

多继承中super的使用

class Father(object):

    def __init__(self, name, *args):
        self.name = name
        super().__init__(*args)


class Mother(object):

    def __init__(self, age, *args):
        self.age = age
        super().__init__(*args)


class Son(Father, Mother):

    def __init__(self, name, age, gender):
        super().__init__(name, age)
        self.gender = gender   

  super简单的说是调用父类的方法,不管是父类的初始化方法还是实例方法都可以;但实质并非是这样,比如Father类和Mother类中的super并非都是调用object的初始化方法,否则也达不到初始化Son实例的效果。事实上这与MRO有关,当然你可能不会太明白上例的用法,请接着往下看。

关于MRO

  MRO:method resolution order 是python类继承方法或属性的解析顺序即寻找顺序,示例如下:

class Father(object):

    def __init__(self, name, *args):
        self.name = name
        super().__init__(*args)


class Mother(object):

    def __init__(self, age, *args):
        self.age = age
        super().__init__(*args)


class Son(Father, Mother):

    def __init__(self, name, age, gender):
        super().__init__(name, age)
        self.gender = gender 


if __name__ == '__main__':
    print(Son.__mro__)
    # result: (<class '__main__.Son'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class 'object'>)

  打印 mro,结果是一个类名组成的元组,类名在元组中的顺序就是python解释器寻找方法或属性时查找的顺序。
  正如前文所述,调用父类初始化函数完整的方式是使用super(Son, self).__init__(name),super中第一个参数传递Son即表示调用mro元组中类名为Son后面紧邻类的初始化方法即Father类的初始化方法;若不传递参数则默认传递当前类名,所以可以简写为super().__init__(name)。因此使用super实质上调用的是在mro元组中排列在当前类的后面类中的方法。
  如此一来我们就可以解释多继承中为啥要这样使用super:首先在Son类中调用super传递两个初始化参数,由于没有指定类名,所以默认为当前类名,super().__init__(name, age)会按照mro的顺序调用 Father中的方法,初始化name;接着多余的参数会通过*args传递给Father类的super方法,此时按照mro顺序会调用Mother类的初始化方法,初始化age。之后已经没有多余的参数了,*args为空元组,由于在Mother中调用了super所以还是会执行object类的初始化方式,不过并不会产生任何影响。此时Son类的实例初始化完毕。
  当然正如我们之前所说的那样,super中传递的类名表示调用此类名在mro元组中后面的类中的方法,所以上面的例子可以这样改写:

class Father(object):

    def __init__(self, name):
        self.name = name


class Mother(object):

    def __init__(self, age):
        self.age = age


class Son(Father, Mother):

    def __init__(self, name, age, gender):
        super(Son, self).__init__(name)    # 调用Father的初始化方法
        super(Father, self).__init__(age)  # 调用Mother的初始化方法
        self.gender = gender

  这样也可以完成初始化的工作,减少了在父类中传递不定参数的麻烦,前提是得知道mro的解析顺序,否则容易传递错初始化参数。

上一篇 下一篇

猜你喜欢

热点阅读