python基础 类(三) 类的继承

这个实例说明子类实例对象调用方法或者访问属性时,
如果找不到该方法或者属性,将在该类的超类中去寻找

class A:
    def get_info(self):
        self.name = "kobe"

class B(A):
    pass

b = B()
b.get_info()
print(b.name)	#可以输出结果 kobe

class b中是没有定义属性name,说明是在父类中去寻找的


# 这个例子说明,子类没有__init__时,会自动调用父类的__init__
class C:
    def __init__(self, name) -> None:
        self.name = name
        print(f"父类初始化的name: {name}")
    def get_name(self):
        print(f'the name of {self} is {self.name}')

class D(C):
    pass

d = D() 
这样会报错说
TypeError: C.__init__() missing 1 required positional argument: 'name'
结合报错的提示可以知道,实例化一个子类时,自动调用了父类的构造函数


d = D('kobe')
d.get_name()    #这样可以正常输出



# 下面例子说明,子类父类都有各自的init时,这2个init函数互不影响
# 子类要实现父类init函数的代码时,要在自己的init函数中调用父类的init函数
class E:
    def __init__(self, name) -> None:
        self.name = name
    def get_name(self):
        print(f'the name of {self} is {self.name}')

class F(E):
    def __init__(self, age) -> None:
        self.age = age

f = F(13)
f.get_name()    #这里会报错说
AttributeError: 'F' object has no attribute 'name'
解决办法为在子类的构造函数中调用其超类的构造函数,以确保相关属性得到初始化,如下


class Animal:
    def __init__(self, hungry):
        self.is_hungry = hungry

    def eat(self):
        if self.is_hungry:
            print('yes, I am hungry')
        else:
            print('no, I am not hungry')

class Bird(Animal):
    def __init__(self, hungry):
        super().__init__(hungry)    #子类中调用父类的构造函数
        # 上面是简写,最好写成,
        #super(Bird,self).__init__(hungry)

    def get_drink(self):
        print('water')

    def get_is_hungry(self):
        print(self.is_hungry)

bird = Bird(True)
bird.get_drink()

一般而言,super()里面第一个参数是另一个类的名称,另一个参数是self
在单继承时,super()函数里面的参数是可以忽略,因为单继承时,只有一个父类的构造函数可以利用
但有多个父类继承时,最好把里面的参数带上,这样才能分辨,super()返回对象调用的__init__函数到底是哪一个父类的__init__函数,否则省略的话易出现实际调用的是非期望类的__init__函数

关于super()官方文档的部分介绍如下

image

关于__mro__属性
image

print(Bird.mro)
结果如下
image

posted @ 2023-11-29 15:57  工作手记  阅读(12)  评论(0编辑  收藏  举报