Python 中调用父类中的方法,super() 函数介绍

1. 概述

super() 返回父类的临时对象,然后可以调用父类的方法。常用于扩展父类的方法,通过使用super() 语句直接调用父类的方法,无需再子类中重新实现, 使用最少的代码来扩展父类的方法。

一个例子:

创建一个矩形类,包含长宽2个属性, 周长和面积2个函数。

class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    def area(self):
        return self.length * self.width

    def perimeter(self):
        return 2 * (self.length + self.width)

 如果我们需要一个正方形的类,可以选择创建一个类

class Square:
    def __init__(self, length):
        self.length = length

    def area(self):
        return self.length * self.length

    def perimeter(self):
        return 4 * self.length

 由于正方形是一个特殊的矩形, 代码中两个类却没什么关系。而通过使用继承来创建类,逻辑上可以反映出正方形和矩形的关系,同时可以减少代码量。

class Square(Rectangle):
    def __init__(self, length):
        super().__init__(length, length)

 super()  返回一个当前对象的父类,所以我们代码中调用的是父类Rectangle的__init__方法,创建一个长和宽相等的矩形。

 2. super() 的作用

下面介绍以下super() 做了些什么

super(SubClass, instance)  两个参数:第一个参数是子类,第二个参数是作为该子类实例的对象

在Python3 中为了使用方便,做了一些简化,向我们之前 Square 类中使用的 super() 等效于 super(Square, self) . 第一个参数指的是子类Square,而第二个参数指的是一个Square对象,self。

我们再创建一个正方体的类

class Cube(Square):
    def volume(self):
        face_area = super(Square, self).area()
        return face_area * self.length

Cube 类中,使用super() 函数的第一个参数是 Square 类, 结果是导致从Square的父类开始寻找area() 方法。 第二个参数self 是一个实例,它为父类的方法提供对象的上下文,例如本例中area函数需要使用的实例属性length。

 3. 多重继承中的super()

除了单继承之外,Python 还支持多继承,一个子类可以继承自多个父类。延续之前的例子,我们

再创建2个类, 三角形(Triangle)和 金字塔(Pyramid) 

class Triangle:
    def __init__(self, base, height):
        self.base = base
        self.height = height

    def area(self):
        return 0.5 * self.base * self.height

class Pyramid(Triangle, Square):
    def __init__(self, base, slant_height):
        self.length = base
        # 斜高, 平面三角形的底到金字塔顶端的距离
        self.slant_height = slant_height

    def area(self):
        bottom_area = super().area()
        plane_area = 0.5 * self.length * self.slant_height * 4
        return bottom_area + plane_area

 我想要求金字塔的表面积 = 底(正方形面积) + 侧面(三角形面积)* 4。 由于Pyramid 继承自 2个父类(三角形和正方形都定义了area方法), 那么当调用super().area()时, 是调用的哪个父类的方法呢。

3.1 mro (method resolution order)

每个类都有一个__mro__属性,描述其继承关系。我们检查以下金字塔类的__mro__可以看到

In [3]: Pyramid.__mro__
Out[3]: (__main__.Pyramid, __main__.Triangle, __main__.Square, object)

 解析顺序为 Pyramid > Triangle > Square > object.   所以当我们调用super().area时, 优先从Triangle中解析,所以调用的三角形的面积公式。

In [4]: pyramid = Pyramid(3,2)
In [5]: pyramid.area()
---------------------------------------------------------------------------
AttributeError: 'Pyramid' object has no attribute 'height'

可以看到,因为金字塔中没有定义 height属性, 导致函数报错。

3.2 解决方法

① 通过修改定义类时父类的顺序, 可以改变__mro__的顺序。将Square 类放到前面

class Pyramid(Square, Triangle):
    def __init__(self, base, slant_height):
        self.length = base
        # 斜高, 平面三角形的底到金字塔顶端的距离
        self.slant_height = slant_height

    def area(self):
        bottom_area = super().area()
        plane_area = 0.5 * self.length * self.slant_height * 4
        return bottom_area + plane_area

 可以看到,输出正常。

In [8]: pyramid = Pyramid(3,2)
In [9]: pyramid.area()
Out[9]: 21.0

 ②,一个更好的方法是, 多继承时应避免同级的父类存在同名函数,将Triangle中的area函数重命名

class Triangle:
    def __init__(self, base, height):
        self.base = base
        self.height = height

    def tri_area(self):
        return 0.5 * self.base * self.height

class Pyramid(Triangle, Square):
    def __init__(self, base, slant_height):
        self.length = base
        # 斜高, 平面三角形的底到金字塔顶端的距离
        self.slant_height = slant_height
        super().__init__(base, slant_height)

    def area(self):
        bottom_area = super().area()
        plane_area = super().tri_area() * 4
        return bottom_area + plane_area

 

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值