类的继承

第12节 类的继承和定制 - 图2
第12节 类的继承和定制 - 图3

  1. class Chinese:
  2. eye = 'black'
  3. def eat(self):
  4. print('吃饭,选择用筷子。')
  5. class Cantonese(Chinese):
  6. # 通过继承,Chinese类有的,Cantonese类也有
  7. pass
  8. # 验证子类可以继承父类的属性和方法,进而传递给子类创建的实例
  9. yewen = Cantonese()
  10. # 子类创建的实例,从子类那间接得到了父类的所有属性和方法
  11. print(yewen.eye)
  12. # 子类创建的实例,可调用父类的属性
  13. yewen.eat()
  14. # 子类创建的实例,可调用父类的方法

第12节 类的继承和定制 - 图4

类的继承之多层继承

第12节 类的继承和定制 - 图5

  1. # 先阅读代码和注释,然后直接运行代码。
  2. class Earthman:
  3. eye_number = 2
  4. # 中国人继承了地球人
  5. class Chinese(Earthman):
  6. eye_color = 'black'
  7. # 广东人继承了中国人,同时也继承了地球人。
  8. class Cantonese(Chinese):
  9. pass
  10. yewen = Cantonese()
  11. print(yewen.eye_number)
  12. print(yewen.eye_color)

类的继承之多重继承

一个类,可以同时继承多个类,语法为class A(B,C,D):。假设我们将“出生在江苏,定居在广东的人”设为一个类Yuesu,那么,它的创建语句则为class Yuesu(Yue,Su)

class Yuesu(Yue,Su)括号里Yue和Su的顺序是有讲究的。和子类更相关的父类会放在更左侧。我认为“出生在江苏,定居在广东的人”在穿着和饮食等方面会更接近广东人,所以将 Yue 放在 Su 的左侧。

所以,广东人创建的实例在调用属性和方法时,会先在左侧的父类中找,找不到才会去右侧的父类找。(可理解为“就近原则”)

  1. class Su:
  2. born_city = 'Jiangsu'
  3. wearing = 'thick' # 穿得较厚
  4. def diet(self):
  5. print('我们爱吃甜。')
  6. class Yue:
  7. settle_city = 'Guangdong'
  8. wearing = 'thin' # 穿得较薄
  9. def diet(self):
  10. print('我们吃得清淡。')
  11. class Yuesu(Yue,Su):
  12. pass
  13. xiaoming = Yuesu()
  14. print(xiaoming.wearing)
  15. print(xiaoming.born_city)
  16. xiaoming.diet()
  17. # 答案
  18. thin
  19. Jiangsu
  20. 我们吃得清淡。

第12节 类的继承和定制 - 图6练习

第12节 类的继承和定制 - 图7

  1. class C0:
  2. name = 'C0'
  3. class C2(C0):
  4. num = 2
  5. class C1:
  6. num = 1
  7. class C3:
  8. name = 'C3'
  9. class C4(C1,C2,C3):
  10. pass
  11. ins = C4()
  12. print(ins.name) # 打印出C0
  13. print(ins.num) # 打印出1

类的定制

定制,可以新增代码

  1. class Chinese:
  2. eye = 'black'
  3. def eat(self):
  4. print('吃饭,选择用筷子。')
  5. class Cantonese(Chinese): # 类的继承
  6. native_place = 'guangdong' # 类的定制
  7. def dialect(self): # 类的定制
  8. print('我们会讲广东话。')
  9. yewen = Cantonese()
  10. print(yewen.eye)
  11. # 父类的属性能用 black
  12. print(yewen.native_place)
  13. # 子类的定制属性也能用 guangdong
  14. yewen.eat()
  15. # 父类的方法能用 吃饭,选择用筷子。
  16. yewen.dialect()
  17. # 子类的定制方法也能用 我们会讲广东话

定制,也可重写代码

  1. class Chinese:
  2. def land_area(self,area):
  3. print('我们居住的地方,陆地面积是%d万平方公里左右。'% area)
  4. class Cantonese(Chinese):
  5. # 直接对方法进行重写
  6. def land_area(self,area):
  7. print('我们居住的地方,陆地面积是%d万平方公里左右。'% int(area * 0.0188))
  8. gonger = Chinese()
  9. yewen = Cantonese()
  10. gonger.land_area(960)
  11. # 我们居住的地方,陆地面积是960万平方公里左右。
  12. yewen.land_area(960)
  13. # 我们居住的地方,陆地面积是18万平方公里左右

拓展

1、实例的对象和类之间的联系

首先,实例属性和类属性:
1)修改类属性,这会导致所有实例属性变化(因为类是模板);
2)修改实例属性,但这不会影响到其他实例,也不会影响到类。因为每个实例都是独立的个体。image.png
其次,实例方法和类方法:
1)重写类方法,这会导致所有实例方法自动被重写;
2)实例方法不可重写
image.png

2、重写类方法”分成两个步骤

1)在类的外部写一个函数,
2)把这个新函数的名字赋值给 类.原始函数:
image.png

3、初始化函数

  1. 初始化函数(方法),也叫构造函数,它的意思是,当你创建一个实例的时候,这个函数就会被调用(自动执行)。
  2. 初始化函数的写法是固定的格式:中间是“init”,这个单词的中文意思是“初始化”,然后前后都要有【两个下划线】,然后init()的括号中,第一个参数一定要写上self,不然会报错。写成def init(self)。
  3. 在初始化方法内部完成类属性的创建,为类属性设置初始值,这样类中的其他方法就能直接、随时调用。不需要再调用init()

image.png
image.png

在这个类中,一旦调用,就会自动执行初始化函数创建类属性
在初始化函数的定义时,也可以设置需要传递的参数位置

在实例化类的时候,可直接手动传入参数
image.png

4、类的继承

类的继承很大程度也是为了避免重复性劳动。比如说当我们要写一个新的类,如果新的类有许多代码都和旧类相同,又有一部分不同的时候,就可以用“继承”的方式避免重复写代码;
同理,在类的继承后,子类重写初始化函数时调用父类的初始化函数,也是因为许多代码都和旧类相同,又有一部分不同的时候,就可以用调用的方式避免重复写代码;
子类创建的实例,同时属于父类
父类创建的实例,不属于子类;
image.png
这个例子属于类的定制和调用,能够理解这个代码,其实对于类的继承最核心的知识就掌握了
image.png

在这个代码中,Knight类继承了Role类

并重新初始化函数,修改了类属性

这里可以改为另一种写法,也就是重写子类初始化函数时,调用父类的初始化函数。或者可以理解为父类方法的继承
image.png
image.png

先看这个,没有继承的类方法调用
image.png

子类继承后,修改了方法,再进行调用
image.png