继承

继承是面向对象一个非常重要的特性,如果没有继承那就不能称为类。

当定义一个类时,可以从现有的类继承,新的类称为子类(Sub Class)或派生类,被继承的类称为基类(Base Class),父类或超类(Super Class)。

派生类定义的语法如下:

class SubClassName(BaseClassName):
    <statement-1>
    ...
    <statement-Nm>

案例:

创建一个Animal类用来表示动物,一个Cat类用来表示猫,一个Dog类用来表示狗。

# 定义一个Animal类表示动物
class Animal:
    
    name = '动物'
    
    def eat(self):
        print('吃东西')
    
    def drink(self):
        print('喝水')
        
    def sleep(self):
        print('睡觉')
    
    def call(self):
        print('喊叫')
# 继承
# 定义一个Cat类继承Animal类表示猫
class Cat(Animal):
    pass
# 定义一个Dog类继承Animal类表示狗
class Dog(Animal):
    pass

这个案例中Cat,Dag继承了Animal类,那么AnimalCat,Dog的父类,Cat,DogAnimal的子类。

继承的具体体现是子类会继承父类的属性和方法。

虽然在CatDog类中没有定义任何的属性和方法,但它们自动继承了父类Animal的属性和方法。

print(dir(Cat))

输出:

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'call', 'drink', 'eat', 'name', 'sleep']

可以在属性中看到call,drink,eat,sleep,name

cat = Cat()
print(cat.name)
cat.eat()
cat.drink()
cat.sleep()
cat.call()

输出:

动物
吃东西
喝水
睡觉
喊叫

多继承

python支持多继承,继承多个父类的子类定义语法如下:

class SubClassName(Base1,Base2,Base3):
    <statement-1>
    ...
    <statement-Nm>

多继承最简单的情况是,父类之间是无关的,这时搜索从父类所继承的属性的操作是深度优先,从左至右的。因此如果某一属性在SubClassName中未找到,则会在Base1中搜索它,然后(递归地)到Base1的父类中搜索,如果找不到,再到Base2中搜索,依此类推。

class A:
    name = 'A'


class B(A):
    pass


class C(B):
    pass


class D:
    name = 'D'


class E(C, D):
    pass


print(E.name)

输出:

A

上面的代码中类的继承关系为:

1660123501191

所以E.name查找的顺序为E,C,B,A,D

有时候,继承关系比这个更复杂,如果D的父类也是A,那结果就不一样了。

class A:
    name = 'A'


class B(A):
    pass


class C(B):
    pass


class D(A):
    name = 'D'


class E(C, D):
    pass


print(E.name)

输出:

D

python中多继承时类的继承顺序时通过mro算法计算出来的,打印类的__mro__属性,可以返回继承顺序:

print(E.__mro__)

输出:

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

所以E.name查找的顺序为E,C,B,D,A,最后输出D.

方法重写

父辈的东西不一定适合我们,我们可以创造属于自己的世界!嘿嘿。

父类的属性和方法也不一定完全适合子类,子类可以通过重写覆盖不合适的属性和方法。

在子类中定义父类中同名的方法和属性会覆盖父类的方法和属性,也叫重写。

案例:

在上面的案例中,虽然Cat,Dog类继承了Animal的属性和方法,但是不能区别CatDog,所以大部分方法和属性不合适,需要重写。

class Cat(Animal):
    name = '猫'
    
    def eat(self):
        print('猫吃鱼')
    
    def call(self):
        print('喵喵叫')
        
        
class Dog(Animal):
    name = '狗'
    
    def eat(self):
        print('狗吃骨头')
    
    def call(self):
        print('汪汪叫')

分别重写了属性name和方法eatcall

cat = Cat()
print(cat.name)
cat.eat()
cat.call()

输出:

猫
猫吃鱼
喵喵叫
dog = Dog()
print(dog.name)
dog.eat()
dog.call()

输出:

狗
狗吃骨头
汪汪叫
posted @ 2022-08-29 14:02  python心蓝  阅读(73)  评论(0编辑  收藏  举报