类的继承,跟人类繁衍的关系相似。
被继承的类称为基类(也叫做父类),继承而得的类叫派生类(也叫子类),这种关系就像人类的父子关系。
继承最大的好处是子类获得了父类的全部变量和方法的同时,又可以根据需要进行修改、拓展。
继承的语法结构是:
class 子类(父类):
举个例子:下面的代码中。先是定义了一个 People 类,里面有一个 speak 方法。然后再定义一个
Student 类,并继承自 People 类。
- ## 父类定义
- class People:
- def __init__(self, name, age, weight):
- self.name = name
- self.age = age
- def speak(self):
- print(f"{self.name} 说: 我{self.age}岁")
-
- ֺ## 单继承示例
- class Student(People):
- def __init__(self, name, age, weight, grade):
- # 调用父类的实例化方法
- People.__init__(self, name, age, weight)
- self.grade = grade
-
-
- #由于继承的机制,Student 实例会拥有 People 类所有属性和方法,比如下边我可以直接调用
- People 类的 speak 方法。
-
- xm = Student(name="小明", age=10, weight=50, grade="三年级")
- xm.speak()
-
- #小明说:我10岁
-
- 如果不想使用父类的方法,也可以重写它以覆盖父类的 speak 方法。
-
- #重写覆盖父类方法
- class Student(People):
- def __init__(self, name, age, weight, grade):
- # 调用父类的实例化方法
- People.__init__(self, name, age, weight)
- self.grade = grade
- #重写父类的speak方法
- def speak(self):
- print(f"{self.name} 说: 我{self.age}岁了,我在读{self.grade}")
-
- #此时,再调用的话,就会调用自己的方法了
- xm = Student(name="小明", age=10, weight=50, grade="三年级")
- xm.speak()
- #小明说:我10岁了,我在读三年级
1.2多继承
Python 还支持多继承,可以继承自多个类。
语法格式:
class 子类(父类1,父类2,父类3....)
举个例子,定义A、B、C、D、E、F、G七个类,C继承了D,B继承了C,F继承了G,E继承了F,最后A继承了B和E。
- #多继承举例
-
- class D:
- def showD(self):
- print('你看到的是D')
- class C(D):
- def age(self):
- print('c的年龄')
-
- class B(C):
- def show(self):
- print("你看到的是B")
- class G:
- def showG(self):
- print('你看到的是G')
- class F(G):
- def showF(self):
- print('你看到的是F')
- class E(F):
- def show(self):
- print("你看到的是E")
-
- class A(B, E):pass
-
- a=A()
- a.show()
- a.showD()
-
- #你看到的是B
- #你看到的是D #因为B没有showD这个方法,所以去D中去找
多继承的顺序使用的是从左向右再深度优先的原则。
MRO 算法
上面的继承案例是只是非常简单的一种场景,在实际应用中,会远比这个来得复杂。
此时如果单纯的将其理解成 从左向右 深度优先 就会发现很场景下想要理清的方法解析顺序(MRO)是非常难的。
在这种情况下,你还可以有两种方法:
1. 使用 __mro__ 来查询
2. 使用 merge算法进行推导
- #MRO算法举例
- class A(object):pass
- class B(A):pass
- class C(A):pass
- class D(B, C):pass
-
- print(D.__mro__)
-
- #(
, , , , )
多态,是指在同一类型下的不同形态。
- #类的多态举例
- class People:
- def speak(self):
- pass
- class American(People):
- def speak(self):
- print("Hello, boys")
- class Chinese(People):
- def speak(self):
- print('你好呀,兄弟!')
-
-
- p1= American()
- p2 = Chinese()
-
- def do_speak(people):
- people.speak()
-
- do_speak(p1)
- do_speak(p2)
-
-
-
- #Hello, boys
- #你好呀,兄弟!
在之前的学习中,对象的属性,我们都是通过把变量值赋值给对象本身来实现的。
- class Student:
- pass
-
- s = Student()
- s.name = "张三"
- s.age = 27
直接赋值会存在一个问题,就是无法对属性值进行合法性较验,比如我给 age 赋值的是负数,在业 务上这种数据是不合法的。但上面那种写法是无法检查出来的。
为了实现属性的合法性校验,Python 引入的 property 属性。
比如把年龄的数据限制在0-100,如果输入-9,就会报错
- #类的 property 属性
-
- class Student:
- @property
- def age(self):
- return self._age
- @age.setter
- def age(self, value):
- if 0 <= value <= 100:
- self._age = value
- else:
- raise ValueError("Valid value must be in [0, 100]")
-
- li = Student()
- li.name='li'
- li.age=-9
- print(li.age)
-
-
-
-
-
- ValueError Traceback (most recent call last)
input-12-5e2d3cfb9ed2> in - 12 li = Student()
- 13 li.name=''
- ---> 14 li.age=-9
- 15 print(li.age)
-
input-12-5e2d3cfb9ed2> in age(self, value) - 8 self._age = value
- 9 else:
- ---> 10 raise ValueError("Valid value must be in [0, 100]")
- 11
- 12 li = Student()
-
- ValueError: Valid value must be in [0, 100]