super函数如何在python项目中使用
super函数如何在python项目中使用?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
功能
super功能:super函数是子类用于调用父类(超类)的一个方法。
用法
1.在子类 __init__() 方法中正确的初始化父类,保证相同的基类只初始化一次。
2.覆盖特殊方法。
3.解决多重继承中,子类重复调用父类方法的问题。
注意
super()继承只能用于新式类,用于经典类时就会报错。
新式类:必须有继承的类,如果无继承的,则继承object
经典类:没有父类,如果此时调用super就会出现错误:『super() argument 1 must be type, not classobj)
在子类__init__()方法中正确初始化父类,保证相同的基类只初始化一次
假如说在父类中实现了一个方法,你想在子类中使用父类的这个方法并且做一定扩展但是又不想完全重写,并且这个场景中的继承属于多继承,那么super()就出场了,可以实现方法的增量修改。
A(父类)有x属性,B(子类)想添加y属性:
classA(object): def__init__(self,x): self.x=x classB(A): def__init__(self,x,y): super(B,self,).__init__(x) self.y=y a=A(2) b=B(2,4) print(a.x) print(b.x,b.y)
覆盖Python特殊方法
classProxy: def__init__(self,obj): self._obj=obj #Delegateattributelookuptointernalobj def__getattr__(self,name): returngetattr(self._obj,name) #Delegateattributeassignment def__setattr__(self,name,value): ifname.startswith('_'): super().__setattr__(name,value)#Calloriginal__setattr__ else: setattr(self._obj,name,value)
在上面代码中,__setattr__() 的实现包含一个名字检查。 如果某个属性名以下划线(_)开头,就通过 super() 调用原始的 __setattr__() , 否则的话就委派给内部的代理对象 self._obj 去处理。 这看上去有点意思,因为就算没有显式的指明某个类的父类, super() 仍然可以有效的工作。
解决多重继承中,子类重复调用父类方法的问题
classBase: def__init__(self): print('Base.__init__') classA(Base): def__init__(self): Base.__init__(self) print('A.__init__')
尽管对于大部分代码而言这么做没什么问题,但是在更复杂的涉及到多继承的代码中就有可能导致很奇怪的问题发生。 比如,考虑如下的情况:
classBase: def__init__(self): print('Base.__init__') classA(Base): def__init__(self): Base.__init__(self) print('A.__init__') classB(Base): def__init__(self): Base.__init__(self) print('B.__init__') classC(A,B): def__init__(self): A.__init__(self) B.__init__(self) print('C.__init__')
如果你运行这段代码就会发现 Base.__init__() 被调用两次,如下所示:
>>>c=C() Base.__init__ A.__init__ Base.__init__ B.__init__ C.__init__ >>>
可能两次调用 Base.__init__() 没什么坏处,但有时候却不是。 另一方面,假设你在代码中换成使用 super() ,结果就很完美了:
classBase: def__init__(self): print('Base.__init__') classA(Base): def__init__(self): super().__init__() print('A.__init__') classB(Base): def__init__(self): super().__init__() print('B.__init__') classC(A,B): def__init__(self): super().__init__()#Onlyonecalltosuper()here print('C.__init__')
运行这个新版本后,你会发现每个 __init__() 方法只会被调用一次了:
>>>c=C() Base.__init__ B.__init__ A.__init__ C.__init__ >>>
为了弄清它的原理,我们需要花点时间解释下Python是如何实现继承的。 对于你定义的每一个类,Python会计算出一个所谓的方法解析顺序(MRO)列表。 这个MRO列表就是一个简单的所有基类的线性顺序表。例如:
>>>C.__mro__ (<class'__main__.C'>,<class'__main__.A'>,<class'__main__.B'>, <class'__main__.Base'>,<class'object'>) >>>
为了实现继承,Python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。 我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
子类会先于父类被检查
多个父类会根据它们在列表中的顺序被检查
如果对下一个类存在两个合法的选择,选择第一个父类
关于 super函数如何在python项目中使用问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注恰卡编程网行业资讯频道了解更多相关知识。
推荐阅读
-
Python中怎么动态声明变量赋值
这篇文章将为大家详细讲解有关Python中怎么动态声明变量赋值,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文...
-
python中变量的存储原理是什么
-
Python中怎么引用传递变量赋值
这篇文章将为大家详细讲解有关Python中怎么引用传递变量赋值,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文...
-
python中怎么获取程序执行文件路径
python中怎么获取程序执行文件路径,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的...
-
Python中如何获取文件系统的使用率
Python中如何获取文件系统的使用率,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴...
-
Python中怎么获取文件的创建和修改时间
这篇文章将为大家详细讲解有关Python中怎么获取文件的创建和修改时间,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读...
-
python中怎么获取依赖包
今天就跟大家聊聊有关python中怎么获取依赖包,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据...
-
python怎么实现批量文件加密功能
-
python中怎么实现threading线程同步
小编给大家分享一下python中怎么实现threading线程同步,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!...
-
python下thread模块创建线程的方法
本篇内容介绍了“python下thread模块创建线程的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来...