天天看點

Python面向對象OOP之: super()

作者:洪較瘦不着調退役it人

class繼承的一些知識

  • Python 中的繼承
  • Python 中的多重繼承
  • super()原理
  • 單繼承中的 作super()
  • 多重繼承中的 作super()

如果 有使用面向對象語言的經驗, 已經熟悉super() 的功能。

子類可以通路p這綿超類(父類)中的方法。super()

單繼承

子類隻繼承一個父類:Square是單繼承的Rectangle

class Square(Rectangle):           
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 + 2 * self.width

# Here we declare that the Square class inherits from the Rectangle class
class Square(Rectangle):
    def __init__(self, length):
        super().__init__(length, length)           
>>> square = Square(4)
>>> square.area()           

可以看到 Square繼承 Rectangle類,自動擁有了你類的area方法

在此示例中,Square是超類(父類),并且Rectangle是子類。

super() 能做什麼

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

class Cube(Square):
    def surface_area(self):
        face_area = super().area()
        return face_area * 6

    def volume(self):
        face_area = super().area()
        return face_area * self.length           

Square正方形類的長寬是相同的

def __init__(self, length):
        super().__init__(length, length)           
>>> cube = Cube(3)
>>> cube.surface_area()
54
>>> cube.volume()
27           
super().__init__(length, length)           

super()将委托對象傳回到父類,是以 可以直接在其上調用 的方法:。super().area()

其實很容易了解 super()代表的是父類代理對象,是以可以使用父類的相關方法。

深入探究super()

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 + 2 * self.width

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

這裡 Square在nit中直接指定父類Rectangle的init方法

super(Square, self).__init__(length, length)           

繼續看下面的例子

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

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

face_area = super(Square, self).area()這裡我們使用了父類的area方法

super()在多重繼承中的作用

Python面向對象OOP之: super()
class Triangle:
    def __init__(self, base, height):
        self.base = base
        self.height = height

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

class RightPyramid(Triangle, Square):
    def __init__(self, base, slant_height):
        self.base = base
        self.slant_height = slant_height

    def area(self):
        base_area = super().area()
        perimeter = super().perimeter()
        return 0.5 * perimeter * self.slant_height + base_area           

RightPyramid繼承了兩個類 Triangle,Square,并且這兩個父類都有area這個方法,下面的代碼會有問題。

Python面向對象OOP之: super()
>> pyramid = RightPyramid(2, 4)
>> pyramid.area()
Traceback (most recent call last):
  File "shapes.py", line 63, in <module>
    print(pyramid.area())
  File "shapes.py", line 47, in area
    base_area = super().area()
  File "shapes.py", line 38, in area
    return 0.5 * self.base * self.height
AttributeError: 'RightPyramid' object has no attribute 'height'           

那麼子類會優先使用哪個父類的area方法呢?接着多繼承的方法查找順序

方法解析順序

類有一個屬性__mro__來觀察方法的查找順序

>>> RightPyramid.__mro__
(<class '__main__.RightPyramid'>, <class '__main__.Triangle'>, 
 <class '__main__.Square'>, <class '__main__.Rectangle'>, 
 <class 'object'>)           

調用 area方法報錯可以看到AttributeError: 'RightPyramid' object has no attribute 'height'

說明它使用的是Triangle類中的area方法,通過觀察 __mro__的輸出發現查找順序是因為area同時在 Triangle,Square這兩個類中,但是它會按照下面的順序查找方法,是以會先使用Triangle中的area方法

RightPyramid-----> Triangle--> Square

未完待續

如何解決多繼承中的同名方法調用問題

Python面向對象OOP之: super()