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()官方文档的部分介绍如下
关于__mro__属性
print(Bird.mro)
结果如下