最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

super在多继承中的调用细节

来源:动视网 责编:小采 时间:2020-11-27 14:27:43
文档

super在多继承中的调用细节

super在多继承中的调用细节:注:此处以python 3为运行环境,例子摘自《python cookbook》第8章。 python中若子类要实现父类的初始化,主要有两种方法,第一种是直接通过父类名,第二种是利用super方法。在单继承时两者没什么区别,但在多继承时就需要注意一些细微的差距了。实例解释才是
推荐度:
导读super在多继承中的调用细节:注:此处以python 3为运行环境,例子摘自《python cookbook》第8章。 python中若子类要实现父类的初始化,主要有两种方法,第一种是直接通过父类名,第二种是利用super方法。在单继承时两者没什么区别,但在多继承时就需要注意一些细微的差距了。实例解释才是


注:此处以python 3为运行环境,例子摘自《python cookbook》第8章。

python中若子类要实现父类的初始化,主要有两种方法,第一种是直接通过父类名,第二种是利用super方法。在单继承时两者没什么区别,但在多继承时就需要注意一些细微的差距了。实例解释才是硬道理!
1、利用父类名的情况:

Python代码

class Base:

def __init__(self):

print('Base.__init__')

class A(Base):

def __init__(self):

Base.__init__(self)

print('A.__init__')

class B(Base):

def __init__(self):

Base.__init__(self)

print('B.__init__')

class C(A,B):

def __init__(self):

A.__init__(self)

B.__init__(self)

print('C.__init__')


此时实例化C类会输出如下:

Python代码

>>> c = C()

Base.__init__

A.__init__

Base.__init__

B.__init__

C.__init__

>>>


从中可看出Base类被调用了两次。这想必在很多情况下都不是我们想要的结果,所以此时可考虑用super方法。

2、利用super的情况:

Python代码

class Base:

def __init__(self):

print('Base.__init__')

class A(Base):

def __init__(self):

super().__init__()

print('A.__init__')

class B(Base):

def __init__(self):

super().__init__()

print('B.__init__')

class C(A,B):

def __init__(self):

super().__init__() # Only one call to super() here

print('C.__init__')


此时再实例化C类的输出为:

Python代码

>>> c = C()

Base.__init__

B.__init__

A.__init__

C.__init__

>>>


可看出Base类是不是只调用了一次啊!但很遗憾的是,这并不是促使我写这篇博客记录的原因,因为如果仔细观察的话,虽说Base类的确如预期只调用了一次,但你有没有发觉是先输出“B.__init__”而后才输出的“A.__init__”?而且为什么这样就使得Base只初始化了一次?想必你也有点懵逼了吧?其实这一切都得“怪罪”于super在多继承时的调用过程。python在实现一个类(不仅是继承)时,会产生一个方法生成解析顺序列表,该列表可通过类属性 __mro__ 查看之,如本例中是这样的:

Python代码

>>> C.__mro__

(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>,

<class '__main__.Base'>, <class 'object'>)

>>>


所以在搜索一个属性或方法时,它就会按照这个列表遍历每个类,直到找到第一个匹配这个属性或方法的类为止。而在继承中使用super时,解释器会每遇到一次super就会在该列表上搜索下一个类,直到不再遇到super或列表遍历完为止,然后再类似递归逐层返回。因此本例中搜索过程为:C中遇到super --> 搜索列表中的下一个类,即A --> A中再次遇到super,搜索B --> B中super再现,搜索Base --> 初始化Base类,递归返回。
为了更好的解释该过程,现在请注释掉B类的super所在行:

Python代码

class B(Base):

def __init__(self):

#super().__init__()

print('B.__init__')

class C(A,B):

def __init__(self):

super().__init__() # Only one call to super() here

print('C.__init__')


再次实例化C类,输出如下:

Pythonn代码

>>> c = C()

B.__init__

A.__init__

C.__init__


Base类不再产生输出!为什么?因为B中没了super后,就阻断了列表去搜索Base类,所以也就没有初始化Base了!

文档

super在多继承中的调用细节

super在多继承中的调用细节:注:此处以python 3为运行环境,例子摘自《python cookbook》第8章。 python中若子类要实现父类的初始化,主要有两种方法,第一种是直接通过父类名,第二种是利用super方法。在单继承时两者没什么区别,但在多继承时就需要注意一些细微的差距了。实例解释才是
推荐度:
标签: 使用 调用 引用
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top