【二十四】Python中super()详解及应用场景举例(1)
【1】作用
super
也是一个类,是的。他不是一个方法也不是一个内置的关键字。
class A:
pass
print(type(super(A)))
# <class 'super'>
- 直接通过查看
super
的源码也可以看出它是一个类
class super(object):
"""
super() -> same as super(__class__, <first argument>)
super(type) -> unbound super object
super(type, obj) -> bound super object; requires isinstance(obj, type)
super(type, type2) -> bound super object; requires issubclass(type2, type)
Typical use to call a cooperative superclass method:
class C(B):
def meth(self, arg):
super().meth(arg)
This works for class methods too:
class C(B):
@classmethod
def cmeth(cls, arg):
super().cmeth(arg)
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass
def __get__(self, *args, **kwargs): # real signature unknown
""" Return an attribute of instance, which is of type owner. """
pass
def __init__(self, type1=None, type2=None): # known special case of super.__init__
"""
super() -> same as super(__class__, <first argument>)
super(type) -> unbound super object
super(type, obj) -> bound super object; requires isinstance(obj, type)
super(type, type2) -> bound super object; requires issubclass(type2, type)
Typical use to call a cooperative superclass method:
class C(B):
def meth(self, arg):
super().meth(arg)
This works for class methods too:
class C(B):
@classmethod
def cmeth(cls, arg):
super().cmeth(arg)
# (copied from class doc)
"""
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __repr__(self, *args, **kwargs): # real signature unknown
""" Return repr(self). """
pass
__self_class__ = property(lambda self: type(object))
"""the type of the instance invoking super(); may be None
:type: type
"""
__self__ = property(lambda self: type(object))
"""the instance invoking super(); may be None
:type: type
"""
__thisclass__ = property(lambda self: type(object))
"""the class invoking super()
:type: type
"""
【2】纠正(super
就是用来调用父类方法的,这是一个错误的观点!)
class A:
def __init__(self):
print("A")
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__()
D()
# D
# B
# C
# A
-
如果按照“
super
就是用来调用父类的方法的”这样的理解来看,那上述代码的执行的过程应该为:print("D")
- 【调用super会先后执行B和C】
- 先执行B:
print("B")
- 【调用super执行A】
print("A")
- 【调用super会先后执行B和C】
- 后执行C:
print("C")
- 【调用super执行A】
print("A")
-
执行结果理论应该为:D B A C A
-
但实际情况却是:D B C A
-
所以说“
super
就是用来调用父类的方法的”这个说法是错误的! -
实际上
super
的调用是遵循Python的【MRO(方法解析顺序)】来执行的,在Python3中,MRO是基于C3算法来实现的。
【3】使用场景
- 1.假如我们继承的多个父类有同名的方法
- 可以使用
super
来指定使用哪个父类的方法
- 可以使用
class A:
def test(self):
print('A')
class B:
def test(self):
print('B')
class C(A, B):
def __init__(self):
super().test() # 调用A类中的test方法
super(C, self).test() # 调用A类中的test方法
super(A, self).test() # 调用B类中的test方法
C()
# A
# A
# B
- 2.当我们在子类中使用父类的一个方法并且想对其做一定扩展又不想完全重写,那么使用super()就可以实现方法的增量修改:
- 举一个例子,如果我们想把list中的
append
的方法改为中文添加
应该怎么做呢? - 并且python中list调用
append
方法是没有返回值的,我们想在添加元素操作成功后加一个返回值返回成功
又该如何操作呢?
- 举一个例子,如果我们想把list中的
- 首先看通过调用原来的
list
的执行结果
a=list()
res=a.append(1)
print(res)
# None
- 可以看到调用
append
方法后返回的值为None
- 现在我们通过
super
进行重写- 让其具有返回值并可以直接通过中文来调用
append
:
- 让其具有返回值并可以直接通过中文来调用
class 列表(list):
def 添加(self, *args, **kwargs):
super().append(*args, **kwargs)
return "添加成功"
x = 列表()
res = x.添加(1)
print(res)
print(x)
# 添加成功
# [1]
【4】总结
super
实际上还是很常用的- 比如在restfremework中
- 需要重写其响应结果的Response信息的时候
- 除了通过django的中间件实现
- 也可以使用
super
重写其dispatch
来实现。
- 比如在restfremework中