python super的使用方法及实例详解

作者:yaominghui 时间:2023-08-19 11:04:49 

功能

super功能:super函数是子类用于调用父类(超类)的一个方法。

用法

1.在子类 __init__() 方法中正确的初始化父类,保证相同的基类只初始化一次。

2.覆盖特殊方法。

3.解决多重继承中,子类重复调用父类方法的问题。

注意

super()继承只能用于新式类,用于经典类时就会报错。

新式类:必须有继承的类,如果无继承的,则继承object

经典类:没有父类,如果此时调用super就会出现错误:『super() argument 1 must be type, not classobj)

在子类__init__()方法中正确初始化父类,保证相同的基类只初始化一次

假如说在父类中实现了一个方法,你想在子类中使用父类的这个方法并且做一定扩展但是又不想完全重写,并且这个场景中的继承属于多继承,那么super()就出场了,可以实现方法的增量修改。

A(父类)有x属性,B(子类)想添加y属性:


class A(object):
 def __init__(self,x):
   self.x = x
class B(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特殊方法


class Proxy:
 def __init__(self, obj):
   self._obj = obj

# Delegate attribute lookup to internal obj
 def __getattr__(self, name):
   return getattr(self._obj, name)

# Delegate attribute assignment
 def __setattr__(self, name, value):
   if name.startswith('_'):
     super().__setattr__(name, value) # Call original __setattr__
   else:
     setattr(self._obj, name, value)

在上面代码中,__setattr__() 的实现包含一个名字检查。 如果某个属性名以下划线(_)开头,就通过 super() 调用原始的 __setattr__() , 否则的话就委派给内部的代理对象 self._obj 去处理。 这看上去有点意思,因为就算没有显式的指明某个类的父类, super() 仍然可以有效的工作。

解决多重继承中,子类重复调用父类方法的问题


class Base:
 def __init__(self):
   print('Base.__init__')
class A(Base):
 def __init__(self):
   Base.__init__(self)
   print('A.__init__')

尽管对于大部分代码而言这么做没什么问题,但是在更复杂的涉及到多继承的代码中就有可能导致很奇怪的问题发生。 比如,考虑如下的情况:


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__')

如果你运行这段代码就会发现 Base.__init__() 被调用两次,如下所示:


>>> c = C()
Base.__init__
A.__init__
Base.__init__
B.__init__
C.__init__
>>>

可能两次调用 Base.__init__() 没什么坏处,但有时候却不是。 另一方面,假设你在代码中换成使用 super() ,结果就很完美了:


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__')

运行这个新版本后,你会发现每个 __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列表并遵循如下三条准则:

  • 子类会先于父类被检查

  • 多个父类会根据它们在列表中的顺序被检查

  • 如果对下一个类存在两个合法的选择,选择第一个父类

老实说,你所要知道的就是MRO列表中的类顺序会让你定义的任意类层级关系变得有意义。

当你使用 super() 函数时,Python会在MRO列表上继续搜索下一个类。 只要每个重定义的方法统一使用 super() 并只调用它一次, 那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次。 这也是为什么在第二个例子中你不会调用两次 Base.__init__() 的原因。

来源:https://www.cnblogs.com/-wenli/p/11343451.html

标签:python,super,用法
0
投稿

猜你喜欢

  • 如何将你的应用迁移到Python3的三个步骤

    2022-03-17 08:59:48
  • JavaScript实现烟花特效(面向对象)

    2024-02-26 22:44:50
  • Python之捕捉异常详解

    2022-06-10 02:27:30
  • Python collections.deque双边队列原理详解

    2022-02-21 04:25:00
  • php中preg_match的isU代表什么意思

    2024-05-03 15:13:51
  • Python中pygame的mouse鼠标事件用法实例

    2021-02-09 12:21:41
  • Python在字典中查找元素的3种方式

    2023-08-07 21:33:35
  • pytest conftest.py文件的使用讲解

    2023-10-16 14:22:44
  • Python制作动态字符画的源码

    2022-11-18 09:13:48
  • Django 全局的static和templates的使用详解

    2021-10-04 10:13:29
  • Python网络爬虫项目:内容提取器的定义

    2021-05-29 21:51:43
  • 深入解析Python中的集合类型操作符

    2022-06-19 01:04:33
  • selenium3+python3环境搭建教程图解

    2022-09-04 14:47:16
  • Python OpenCV 使用滑动条来调整函数参数的方法

    2022-05-20 06:43:48
  • Python如何提取csv数据并筛选指定条件数据详解

    2022-07-20 22:47:59
  • macOS安装Solr并索引MySQL

    2024-01-17 13:57:08
  • golang gorm错误处理事务以及日志用法示例

    2024-04-25 13:18:50
  • 对python cv2批量灰度图片并保存的实例讲解

    2022-06-11 18:21:36
  • Django实现自定义路由转换器

    2021-09-10 05:49:04
  • pandas求两个表格不相交的集合方法

    2022-03-08 01:15:41
  • asp之家 网络编程 m.aspxhome.com