Python3里的super()和__class__使用介绍

yipeiwu_com7年前Python基础

子类里访问父类的同名属性,而又不想直接引用父类的名字,因为说不定什么时候会去修改它,所以数据还是只保留一份的好。其实呢,还有更好的理由不去直接引用父类的名字,参见 Python's super() considered super! | Deep Thoughts by Raymond Hettinger

这时候就该 super() 登场啦——

复制代码 代码如下:

class A:
  def m(self):
    print('A')

class B(A):
  def m(self):
    print('B')
    super().m()

B().m()


当然 Python 2 里 super() 是一定要参数的,所以得这么写:
复制代码 代码如下:

class B(A):
  def m(self):
    print('B')
    super(B, self).m()

需要提到自己的名字。这个名字也是动态查找的,在这种情况下替换第三方库中的类会出问题。

super() 很好地解决了访问父类中的方法的问题。那么,如果要访问父类的父类(准确地说,是方法解析顺序(MRO)中位于第三的类)的属性呢?

比如,B 类是继承 A 的,它重写了 A 的 m 方法。现在我们需要一个 C 类,它需要 B 类的一些方法,但是不要 B 的 m 方法,而改用 A 的。怎么间接地引用到 A 的 m 方法呢?使用self.__class__肯定是不行的,因为 C 还可能被进一步继承。

从文档中我注意到,super 的实现是通过插入一个名为 __class__ 的名字来实现的(super 会从调用栈里去查找这个 __class__ 名字)。所以,就像文档里暗示的,其实可以直接在定义方法时访问 __class__ 名字,它总是该方法被定义的类。继续我们的单字母类:

复制代码 代码如下:

class C(B):
  def m(self):
    print('C')
    # see the difference!
    print(__class__.__mro__)
    print(self.__class__.__mro__)
    __class__.__mro__[2].m(self)

class D(C):
  def m(self):
    print('D')
    super().m()

o = D()
o.m()


会得到:
复制代码 代码如下:

D
C
(<class 't.C'>, <class 't.B'>, <class 't.A'>, <class 'object'>)
(<class 't.D'>, <class 't.C'>, <class 't.B'>, <class 't.A'>, <class 'object'>)
A

不过,PyPy 并不支持这个 __class__ 名字。

相关文章

Python3数据库操作包pymysql的操作方法

Python3数据库操作包pymysql的操作方法

以下代码实现环境是mac系统,本地配置mysql服务端和navicat premium客户端,python环境是配置了pymysql的anaconda3。 首先,与数据库建立connec...

使用Python的turtle模块画国旗

使用Python的turtle模块画国旗

Python的turtle模块画国旗主要用到两个函数:draw_rentangle和draw_star。 至于函数的调用就和我们学的C,C++是一样的。对于turtle画国旗的程序中,首...

pymysql模块的使用(增删改查)详解

一、pymysql的下载和使用 之前我们都是通过MySQL自带的命令行客户端工具mysql来操作数据库,那如何在python程序中操作数据库呢?这就用到了pymysql模块,该模块本质...

Python 序列化 pickle/cPickle模块使用介绍

Python序列化的概念很简单。内存里面有一个数据结构,你希望将它保存下来,重用,或者发送给其他人。你会怎么做?这取决于你想要怎么保存,怎么重用,发送给谁。很多游戏允许你在退出的时候保存...

使用beaker让Facebook的Bottle框架支持session功能

bottle是一个小型web框架,很小只有一个文件,但功能确很强大,学起来也简单,简单和小巧的同时也有很多不足,某些功能支持还不是很完善,比如session.但是也有它自身的好处,我们可...