一、super
1、概念

super:是一个内置的代理类对象而不是一个函数对象,

作用:运行super()会得到一个代理实例对象,即一个委托类的父类或者兄弟类方法调用的代理对象。

2、原型

super([type1][, object-or-type2])

3、参数说明

type1:指委托类
object-or-type2:当该参数为object时必须满足isinstance(object, type1) == True:当该参数为type2时,必须满足issubclass(type2, type1) == True。

使用super时可以直接省略掉参数写为super(),因为解释器在执行时会自动添加相应的参数。

4、原理

目前能力有限,还写不出一个功能类似super()的代理类。

此处只是为了用python代码说明super内部实现的逻辑,并不是真实的super相关代码

def super(type1, obj_type2):
    obj_type2 = obj_type2
    if isinstance(obj_type2, type1):
        mro_list = obj_type2.__class__.mro()
    elif issubclass(obj_type2, type1):
        mro_list = obj_type2.mro()
    else:
        print("参数有误!!!")
        raise Exception
    next_class = mro_list[mro_list.index(type1) + 1]
    return next_class

在首次调用时,MRO就已经被确定,是object所属类(即C)的MRO或type2所对应的MRO,因此type1参数的作用就是从已确定的MRO中找到位于其后紧邻的类,作为再次调用super()时查找该方法的下一个类。

5、要点:
  • super()使用的时候需要传递两个参数,在类中可以省略不写,我们使用super()来找父类或者兄弟类的方法;
  • super()是根据第二个参数来计算MRO,根据顺序查找第一个参数类后的方法。
  • super()第二个参数是类,得到的方法是函数,使用时要传self参数。第二个参数是对象,得到的是绑定方法,不需要再传self参数。

给使用super()的一些建议

  • super()调用的方法要存在;
  • 传递参数的时候,尽量使用*args 与**kwargs;
  • 父类中的一些特性,比如【】、重写了__getattr__,super对象是不能使用的。
  • super()第二个参数传的是类的时候,建议调用父类的类方法和静态方法。
二、多继承
1、多继承

Python虽然语法上支持多继承,但是却不推荐使用多继承,而是推荐使用单继承,这样可以保证编程思路更清晰,也可以避免不必要的麻烦。

当以一个子类有多个直接父类时,该子类会继承得到所有父类的方法,但是如果其中有多个父类包含同名方法会发生什么?此时排在前面的父类中的方法会“遮蔽”后面父类中的方法。

示例:

python多重try python多重继承super父类参数_python多重try

class Base:
    def __new__(cls, base):
        print(cls)
        print("Base.__new__")
        return super(Base, cls).__new__(cls)

    def __init__(self, base):
        print("Base.__init__")
        self.base = base
        print(self.base)


class A(Base):
    def __new__(cls, base, a, b):
        """
        __new__此处不仅接收参数base,a, 还须接受参数b因为
        C.__mro__ = (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>)
        python3支持多继承,搜索父类及兄弟类时是按照广度优先搜索遍历,遍历结果也就是C.__mro__从左到右的顺序,
        此处下一个时A的兄弟类B
        """
        print(cls)
        print("A.__new__")
        return super(A, cls).__new__(cls, base, b)

    def __init__(self, base, a, b):
        super(A, self).__init__(base, b)
        print("A.__init__")
        self.a = a
        print(self.a)


class B(Base):
    def __new__(cls, base, b):
        print(cls)
        print("B.__new__")
        return super(B, cls).__new__(cls, base)

    def __init__(self, base, b):
        super(B, self).__init__(base)
        print("B.__init__")
        self.b = b
        print(self.b)


class C(A, B):
    __c_class__ = 4

    def __new__(cls, base, a, b, c):
        print(cls)
        print("C.__new__")
        return super(C, cls).__new__(cls, base, a, b)

    def __init__(self, base, a, b, c):
        super(C, self).__init__(base, a, b)
        print("C.__init__")
        self.c = c
        print(self.c)


print(C.__mro__)
test = C(base=0, a=1, b=2, c=3)
print(test.base, test.a, test.b, test.c)


"""
运行结果:
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>)
<class '__main__.C'>
C.__new__
<class '__main__.C'>
A.__new__
<class '__main__.C'>
B.__new__
<class '__main__.C'>
Base.__new__
Base.__init__
0
B.__init__
2
A.__init__
1
C.__init__
3
0 1 2 3

Process finished with exit code 0
"""
2、多继承协同

示例:

class Minix1:
    """该混合类为header列表末尾添加data1"""

    def get_header(self):
        print('run Minix1.get_header')
        ctx = super().get_header()
        ctx.append('data1')
        return ctx


class Minix2:
    """该混合类为header列表头部添加data2"""

    def get_header(self):
        print('run Minix2.get_header')
        ctx = super().get_header()
        ctx.insert(0, 'data2')
        return ctx


class Header:
    header = []

    def get_header(self):
        print('run Headers.get_header')
        return self.header if self.header else []


class Final(Minix1, Minix2, Header):

    def get_header(self):
        return super().get_header()


print(Final.mro())
header = Final().get_header()
print(header)


"""
[<class '__main__.Final'>, <class '__main__.Minix1'>, <class '__main__.Minix2'>, <class '__main__.Header'>, <class 'object'>]
run Minix1.get_header
run Minix2.get_header
run Headers.get_header
['data2', 'data1']

Process finished with exit code 0
"""

看来,运行得很成功,我们实现了多继承协同工作的目标,通过混合不同个类,来模块化地快速得到想要的header属性。而这种工作方法,通过单纯的重写某个方法根本无法实现的,因为重写任何方法,它会在MRO列表中找到最优先(也就是最靠前)的拥有同名方法的类,然后调用该方法,并且终止检索,某项属性仅仅会被一个方法所影响。

这个特性,在Django的CBV中有相当程度的应用。