1,什么是继承?
-
继承指的是一种关系,必须存在两个对象才能产生这种关系
-
被继承的称为父,继承的一方称为子
-
在程序中,继承指的是类与类之间的关系
2,为什么要使用继承?
继承可以扩展已存在的代码模块(类)
在程序中,通过继承可以直接使用父类已有的代码
3,怎么使用继承
继承类的语法
class Father:
pass
class Som(Father): #子类后面加上括号,写上父类的名称
pass
在python中,一个字类可以有多个父类,多个父类在括号中用逗号隔开
继承父类中对象和方法的语法
class Parent:
year = 2018
def coding(self):
print('coding')
class Sub(Parent):
pass
print(Sub.year)
s1 = Sub()
s1.coding()
4,继承对编程的作用
假设有个学生管理需求:
class Student:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def study(self):
print('正在学习中')
def eat(self):
print('正在吃饭中')
学生的属性和技能也适用于老师,此时可以引用继承,减少代码的冗余
class Teacher(Student):
pass
t1 = Teacher('alex',30,'man')
t1.eat()
t1.study()
从逻辑上来说,如果学生有打游戏的技能,而老师并没有这个需求,因此继承到了老师并不需要的技能
正确姿势: 抽取公共的父类 (抽象)
抽象 : 抽取多个类中相同得部分,形成另一个类
把学生和老师共有的内容抽到另一个类中,学生和老师分别继承这个类,这样就避免了一个类继承到不需要的内容 因此应该先抽象,再继承
小结:
-
通过继承,避免了重复代码的编写。
-
继承的作用是可以直接使用父类已有的代码
-
通过抽象,避免了一个类继承到不需要的内容
-
抽象的作用是存储多个子类相同的属性和技能
-
正确地顺序应该先抽象,再继承
1,派生
class Person:
• def __init__(self,name,age,sex):
• self.name = name
• self.age = age
• self.sex = sex
• def sayhi(self):
• print('hello,')
class Student(Person): # 学生属于人类,可以直接继承
• def __init__(self,number): # 加上一些学生特有的属性
• self.number = number
• def study(self):
• print('%s正在学习'%self.name)
-
派生指某个子类继承父类,并且拥有自己独特的属性或技能
-
该子类称之为派生类
-
只要子类中出现任何新内容,这就是一个派生类
2,覆盖
class A:
age = 18#age相同
def f1(self):#f1相同
print(" A f1" )
pass
class B(A):
age1 = 19
def f1(self):#f1
self.f1()
print(" B f1")
b1 = B()
print(b1.age)
b1.f1()
小结:
-
子类出现了与父类重复的名字 称之为覆盖
-
方法1 从父类去调
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def sayhi(self):
print('hello,')
class Student(Person): # 学生属于人类,可以直接继承
def __init__(self,name,age,sex,number): # 加上一些学生特有的属性
#self.name = name
#self.age = age
#self.sex = sex #代码重复
Person.__init__(self,name,age,sex) #在子类访问父类的方式1
self.number = number
def study(self):
print('%s正在学习'%self.name)
stu1 = Student('成龙',20,'man',4235)
print(stu1.__dict__)
方法2 super()函数
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def sayhi(self):
print('hello,')
class Student(Person): # 学生属于人类,可以直接继承
def __init__(self,name,age,sex,number): # 加上一些学生特有的属性
super(Student,self).__init__(name,age,sex) #super()表示特殊的对象
super().__init__(name,age,sex)#效果一样,这是py3的语法
self.number = number
def study_1(self):
super().sayhi() #访问父类的方法1
Person.sayhi(self) #访问父类的方法2
print('%s正在学习'%self.name)
stu1 = Student('成龙',20,'man',4235)
stu1.study_1()
print(stu1.__dict__)
了解,在python2中,super的用法不同。super(Student,self).init()
1,存在一个父类的情况
class A:
age = 10
class B(A):
age = 11
class C(B):
age = 12
c1 = C()
c1.age = 13
print(c1.age)
沿着继承关系找,无论是属性还是方法! 如果没有则报错!
2,存在多个父类的查找顺序
(1) ,继承的父类,没有父类,按照继承顺序,从左往右依次查找
class A:
a = 0
pass
class B:
a = 1
pass
class C:
a = 2
pass
class D(A,B,C):
a = 3
pass
d = D()
d.a = 4
print(d.a)
查找顺序为 : A -- B -- C -- D
(2),深度优先,沿着一条线找到底
继承的父类,存在父类,则先把父类找完 这种查找方式仅仅在非菱形继承(没有共同父类)的情况下
class Q:
a = 10
class A(Q):
a = 0
pass
class W:
a = 11
class B(W):
a = 1
pass
class C:
a = 2
pass
class D(A,B,C):
a = 3
pass
d = D()
d.a = 4
print(d.a)
查找顺序为E -- A -- F -- B --同理
3,广度优先,并非绝对的广度优先,而是基于深度的广度优先。
先是深度优先,如果发现有共同父类,则返回。最后再查找共同父类 该查找顺序是通过C3算法得来
了解:
新式类和经典类
主要针对 python2 和 python3 区分的
所有直接继承或间接继承object的类 都是新式类
object 称之为根类 意思是 所有类 都源自于object类
为什么这么设计?
-
例如:创建对象时,需要申请内存空间,创建新的名称空间,将对象的属性放入名称空间, 这一些了复杂的基础操作,都yo由object来完成 简单地说object提供了一些常用的基础操作
-
即所有类都属于新式类(在python3中)
在python3中默认所有类都是新式类
class S:
pass
class Student(S):
pass
bases__用于查看父类
print(Student.__bases__)
显示属性的查找顺序列表,属性查找属性就是按照该列表来查找的
print(Student.mro())
mro
查看访问路径
"super访问父类内容时 按照mro列表属性查找"
class S:
def f1(self):
print("s f1")
class A(S):
pass
class B(S):
def f1(self):
print("b f1")
pass
class C(A,B):
def f2(self):
print("c f2")
super().f1()
print(C.mro())
c1 = C()
c1.f2()
1,什么是组合
-
多个对象放在一起就是组合
-
一个对象将另一个对象作为自己的属性,就是组合
2,组合的目的
-
处理数据更有效率,有效降低耦合度和代码的冗余
3,组合的实现
-
代码1 是通过继承实现代码的精简
-
-
手机的属性有品牌,价格,运营商,号码
-
如果全部都放到代码1 的父类中,看起来非常的臃肿,管理成本非常高,扩展性变得很差
-
我们可以通过组合实现代码的管理,使代码的可读性和整洁性都得到有效提高
-
代码2 是添加手机功能后通过继承和组合一起实现.
-
组合其实我们在用户交互的练习就实现过了
代码1,继承
class Person:
def __init__(self, name, sex, age, number):
self.name = name
self.sex = sex
self.age = age
self.number = number
class Student(Person):
def __init__(self,name,sex,age,number,game):
super().__init__(name,sex,age,number)
self.game = game
def show_info(self):
print(self.__dict__)
def select(self):
print('%s正在选课'%self.name)
class Teacher(Person):
def __init__(self,name,sex,age,number,teach_class):
super().__init__(name,sex,age,number)
self.teach_class = teach_class
def show_info(self):
print(self.__dict__)
def set_score(self):
print('%s正在为学生打分'%self.name)
s1 = Student('韩信','man',18,51,'王者荣耀')
s1.show_info()
t1 = Teacher('韩信','man',18,51,'王者荣耀')
t1.show_info()
代码2 ,组合的形式
class Phone:#组合的代码
def __init__(self,phonenumber,operator,address):
self.phonenumber = phonenumber
self.operator = operator
self.address = address
def call(self,t):
print("%s 正在拨号 %s" % (t.name,self.phonenumber))
class Person:#父类
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
class Student(Person):#子类
def __init__(self,name,sex,age,number):
super().__init__(name, sex, age)
self.number = number
def show_info(self):
print(self.__dict__)
def select_cursor(self):
print("%s 正在选课...." % self.name)
class Teacher(Person):#子类
def __init__(self,name,sex,age,salary,level):
super().__init__(name,sex,age)
self.salary = salary
self.level = level
def set_score(self):
print("%s 正在为学生打分..." % self.name)
stu = Student("乔峰","男",38,"007")
p1 = Phone("1999999999","中国小米移动","上海浦东")
stu.q = p1 #这里的q是变量名,相当于把p1赋值给q,通过stu来调用
stu.q.call(stu) #不能直接stu.p1.call()