我们一直在说面向对象扩展性高,从来不知道他的扩展性高体现在哪些方面,接下来我们就来介绍他的三大特性,三大特性分别是继承,多肽和封装,他的特性也是我们以后使用面向对象的一些技巧,第一个我们来说的就是继承。
1. 继承的基本介绍
什么是继承
继承是一种新建类的方式,我以前定义的类都是class关键字加类名,在Python中支持多继承,就是一个儿子可以继承多个爹,这一点和其他的某些语言不同
从字面意思上理解就是你继承你爹的东西,他继承他爹的东西,继承就像一种遗传的关系,你爹有钱,你也有钱,要是你没钱,那可能你是你爹充话费送的,你爹有一套房子,你也可以跑进去住一下,当然如果你自己有房子,肯定会优先住你自己房子
继承新建的类称为子类或者派生类,被继承的类称为,父类,基类或者超类,子类会遗传父类的属性
假如你爹给你留了一个亿,你还有必要像其他同学一样苦逼呵呵的在这学Python吗,你就可以直接拿着这个钱来花,不用在自己挣钱,不用自己造了,可事实上你爹一毛都没留给你,所以你要靠自己。
为什么要用继承
所以使用继承就是为了减少代码冗余
怎么用继承
继承应该有爹有儿子,下面我们来写代码
class ParentClass1:
pass
class ParentClass2:
pass
# 单继承,原来类名后面直接加冒号,现在我们可以先加括号,括号里面写他的父类
class SubClass1(ParentClass1):
pass
# Python中支持多继承
class SubClass2(ParentClass1, ParentClass2):
pass
# base是基础的意思,这个方法是查看他的父类
print(SubClass1.__bases__)
print(SubClass2.__bases__)
他的父类会以元祖的形式现实出来
到目前位置我们大概知道了继承是怎么一回事,接下来我们先补充一个简单的小知识点,后面详细介绍
在Python2 中有经典类与新式类之分,
在Python3 中全都为新式类
我们现在用的主流是Python3 ,而Python3 中全都是新式类,所以在Python3中没必要考虑这个,但是我们也需要知道Python2中是怎么用的,具体怎么区分我们后面会详细讲到,现在大家先知道这个概念
2. 如何寻找继承关系
继承是类与类之间的关系,寻找这种继承关系需要先抽象,再具体。什么是抽象呢?就是抽取比较像的部分呀,我们刚学面向对象的时候就是抽取对象中相似的特征总结成了类 ,那么抽取类与类之间相似的地方就总结成了父类
假如现在有这样一个需求,把老师和学生,学生可以自由选择课程学习,老师可以对学生的成绩做评分,按照原来的思路,我应该这样写代码
class DeepshareTeacher:
school = 'deepshare'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def modify_score(self):
print('teacher %s is modifying score' % self.name)
class DeepshareStudent:
school = 'deepshare'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def choose(self):
print('student %s is choosing course' % self.name)
代码写到这里你应可以发现了,这里面有重复的代码,为了避免代码冗余,我们应该使用继承的方式来优化我们的代码
class DeepsharePeople:
school = 'deepshare'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class DeepshareTeacher(DeepsharePeople):
def modify_score(self):
print('teacher %s is modifying score' % self.name)
class DeepshareStudent(DeepsharePeople):
def choose(self):
print('student %s is choosing course' % self.name)
tea1 = DeepshareTeacher('albert',18,'male')
stu1 = DeepshareStudent('张二狗',18,'female')
我们在执行代码实例化对象之前,先来看一下代码里面老师类和学生类里面都没有init这个实例化函数,但是程序没有报错说明他确实完成实例化了,怎么证明呢?
print(tea1.name,tea1.age,tea1.gender)
这就说明了子类中没有init函数,他就会去父类中找,也就是说子类是继承了父类的属性,到此为止,你就会发现我们的代码已经精简了,但是他实现的功能并没有减少
3. 属性查找
有了继承关系以后,接下来我们再来说属性的查找,之前我们说过一个对象查找属性的时候,优先去自己的名称空间中查找,如果找不到就会去自己的类中去找,但是现在你会发现类中居然还有自己的父类,那你试想一下,如果一个对象他自己的名称空间中没有,他的类也没有,那接下来应该找谁?
没错,找他爹,如果他的父类没有并且再有父类呢?找他爷爷
class DeepsharePeople:
school = 'deepshare'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class DeepshareTeacher(DeepsharePeople):
def modify_score(self):
print('teacher %s is modifying score' % self.name)
tea1 = DeepshareTeacher('albert', 18, 'male')
print(tea1.__dict__)
print(tea1.name)
print(DeepshareTeacher.__dict__)
print(DeepsharePeople.__dict__)
print(tea1.school)
4. 派生
刚刚我们讲完了继承,继承的好处是子类可以重用父类的代码,但问题是子类是不是就和父类一模一样就行了,如果这样那你写子类的目的是什么呢?子类有了以子类为准,所以在这里我们再讲一个叫做派生的概念
其实这个概念本章一开始我们就提及到了,假如你爹有一套房子,你可以进去住一下,但是如果你自己有房子,肯定会优先住自己的房子
派生就是在继承的基础上有自己新的东西,如果有自己新的东西,肯定就会以自己新的东西为准
派生:子类定义自己新的属性,如果与父类同名,以子类自己的为准
class DeepsharePeople:
school = 'deepshare'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def f1(self):
print('爹的f1')
class DeepshareTeacher(DeepsharePeople):
def modify_score(self):
print('teacher %s is modifying score' % self.name)
def f1(self):
print('儿子的f1')
tea1 = DeepshareTeacher('albert', 18, 'male')
tea1.f1()
5. 经典类与新式类
一开始的时候我们就引出了这个概念,现在我们来理解一下
新式类:继承object的类,以及该类的子类孙子类,都是新式类
经典类:没有继承object的类,以及该类的子类,孙子类,都是经典类
我们先来看一些object是个什么东东
print(object)
object也是一个类,他就是类的老祖宗,在Python3当中定制了大量的功能,都是自动触发的功能,以此来帮你来完善你编写的类的一些功能。Python3中的类都是新式类,那就必然继承了object,我们来看一下
class Foo:
pass
print(Foo.__bases__)
这说明Python3中一个类没有指定的父类,默认就会继承object类,所以Python3中都是新式类
但如果是在Python2 中呢(解释器已切换到Python2)
class Foo:
pass
print(Foo.__bases__)