本文相关描述主要是个人的认知和见解,如有不当之处,还望各位大佬指正。
个人其他博客地址:
简书:https://www.jianshu.com/u/d6960089b087
掘金:https://juejin.cn/user/2963939079225608
小钟同学 | 文 【原创】| QQ:308711822
前面有介绍了关于多继承问题,其实还涉及到一个子类调用父类的,多次调用的问题。再多继承中子类调用父类的多次调用问题。
通常我们的所知的一个子类调用父类的方法的方式就是:super()。有些时候我们可以理解是子类,调用父类(单继承中),但是在多继承,又是不一样。
在每个类声明之后,Python都会自动为创建一个名为“mro”的内置属性,前面也有说到了多继承的MRO的问题,那在,Python中的super()方法是怎么样的呐?
回到之前的MRO的示例上:
class A1:
def __init__(self):
print("A1")
class A2:
def __init__(self):
print("A1")
class A3:
def __init__(self):
print("A3")
class B1(A1, A2):
def __init__(self):
print("B1")
super().__init__()
class B2(A2):
def __init__(self):
print("B2")
super().__init__()
class B3(A2, A3):
def __init__(self):
print("B3")
super().__init__()
class C1(B1):
def __init__(self):
print("C1")
super().__init__()
class C2(B1, B2):
def __init__(self):
print("C2")
super().__init__()
class C3(B2, B3):
def __init__(self):
print("C3")
super().__init__()
class D(C1, C2, C3):
def __init__(self):
print("D")
super().__init__()
for s in D.mro():
print(s)
d = D()
输出的结果为:
<class '__main__.D'>
<class '__main__.C1'>
<class '__main__.C2'>
<class '__main__.B1'>
<class '__main__.A1'>
<class '__main__.C3'>
<class '__main__.B2'>
<class '__main__.B3'>
<class '__main__.A2'>
<class '__main__.A3'>
<class 'object'>
D
C1
C2
B1
A1
从上面的结果可以看出来。super()的调用顺序也是遵循mro算法。所以如果说是单纯的只是父类方法和属性的调用的说法是不太准确的。
示例:
class A1:
def __init__(self):
print("A1")
class A2:
def __init__(self):
print("A1")
class A3:
def __init__(self):
print("A3")
class B1(A1):
def __init__(self):
print("B1")
A1.__init__(self)
class B2(A2):
def __init__(self):
print("B2")
A2.__init__(self)
class B3(A2, A3):
def __init__(self):
print("B3")
A2.__init__(self)
A3.__init__(self)
class C1(B1):
def __init__(self):
print("C1")
B1.__init__(self)
class C2(B1, B2):
def __init__(self):
print("C2")
B1.__init__(self)
B2.__init__(self)
class C3(B2, B3):
def __init__(self):
print("C3")
B2.__init__(self)
B3.__init__(self)
class D(C1, C2, C3):
def __init__(self):
print("D")
C1.__init__(self)
C2.__init__(self)
C3.__init__(self)
# for s in D.mro():
# print(s)
d = D()
上面的代码,我们的为了调用父类的方法,于是乎,会产生一系列的重复的多次的调用的问题!和上面使用的 super().属性、方法截然不同!
所以我们可以总结的到:super()是一个调用父类的说法是不完全对滴。它也是为了解决多继承问题而出现的。
探究我们的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
"""
super是一个类,它实例化之后得到的是一个代理的对象,而不是得到了我们所说的父类,返回这个代理对象后可以使用它调用父类或者兄弟类的方法。
super()三种调用的方法,使用格式如下:
super() == super(type, obj)=super(class , obj)
总结:
class ApiAdminJsonResponse(HTTPException):
code = 500
api_code = 999
result = None # 结果可以是{} 或 []
message = '成功'
success = True
timestamp = get_timestamp13()
# 默认的支持的跨域处理
customize_headers = {
# 'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*,School-Teacher-Token,school-teacher-token,T-Access-Token,x-access-token,Referer, Accept, Origin, User-Agent,X-Requested-With, Content-Type, X-File-Name',
'Access-Control-Request-Headers': 'Content-Type,Access-Token',
'Content-Type': 'application/json;charset=UTF-8'
}
# 还可以自定义响应头信息
def __init__(self, success=None, code=None, message=None, api_code=None, result=None, headers={}, is_limit_cors=False):
if code:
self.code = code
if message:
self.message = message
if api_code or api_code == 0:
self.api_code = api_code
if result:
self.result = result
if headers:
self.customize_headers.update(headers)
if success != None:
self.success = success
# self.code = code
# self.api_code = api_code
# 是否禁止跨域请求处理
self.is_limit_cors = is_limit_cors
super(ApiAdminJsonResponse, self).__init__(message, None)
def get_body(self, environ=None):
body = dict(
message=self.message,
code=self.api_code,
success=self.success,
result=self.result,
timestamp=self.timestamp,
# 形如request="POST v1/client/register"
# request=request.method + ' ' + self.get_url_no_param()
)
text = dict_to_json(body)
return text
# 重写响应的头部信息----可以自定义返回响应头部信息
def get_headers(self, environ=None):
if self.is_limit_cors:
pass
# del self.customize_headers['Access-Control-Allow-Origin']
if 'Access-Control-Allow-Origin' in self.customize_headers.keys():
del self.customize_headers['Access-Control-Allow-Origin']
return self.customize_headers
@staticmethod
def get_url_no_param():
full_url = str(request.full_path)
main_path = full_url.split('?')
return main_path[0]
原文作者:程序员小钟同学;如有侵权,请联系管理员删除。