一、组合
‘‘‘ 1、什么是组合 组合就是一个类的对象具备某一个属性,该属性的值是指向另外一个类的对象 2、为何用组合 组合也是用来解决类与类直接代码冗余问题的 3、如何用组合 ‘‘‘ # 继承减少代码冗余,但是将类与类进行了强耦合,python不崇尚,所以能不用继承就尽量不用继承 class OldboyPeople: school = ‘oldboy‘ def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class OldboyStudent(OldboyPeople): def __init__(self,name,age,sex,stu_id): OldboyPeople.__init__(self,name,age,sex) self.stu_id=stu_id def choose_course(self): print(‘%s is choosing course‘ %self.name) class OldboyTeacher(OldboyPeople): def __init__(self, name, age, sex, level): OldboyPeople.__init__(self,name,age,sex) #重用父类中的属性(功能)(减少代码冗余)------普通的函数传参,该传几个参数传几个参数 self.level=level def score(self,stu,num): #老师有修改学生成绩的功能,所以将学生对象和修改的成绩传入 stu.score=num print(‘老师[%s]为学生[%s]打分[%s]‘ %(self.name,stu.name,num)) stu1=OldboyStudent(‘猪哥‘,19,‘male‘,1) tea1=OldboyTeacher(‘egon‘,18,‘male‘,10) stu1.choose_course() #学生对象选择课程------猪哥 is choosing course tea1.score(stu1,100) #对象的绑定方法--------老师[egon]为学生[猪哥]打分[100] print(stu1.__dict__) #查看学生的字典属性----{‘name‘: ‘猪哥‘, ‘age‘: 19, ‘sex‘: ‘male‘, ‘stu_id‘: 1, ‘score‘: 100} # #定制课程类 class Course: #将学生和老师对象都有课程属性,所以将他们都有的属性抽出来,重新定义了一个课程类 def __init__(self,name,period,price): #调用类时自动触发 self.name=name self.period=period self.price=price # 查看课程信息 def tell_info(self): msg=""" 课程名:%s 课程周期:%s 课程价钱:%s """ %(self.name,self.period,self.price) print(msg) #定制人类--------老师和学生类都是人类 class OldboyPeople: school = ‘oldboy‘ # 定制人类独有的数据属性 def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class OldboyStudent(OldboyPeople): def __init__(self,name,age,sex,stu_id): OldboyPeople.__init__(self,name,age,sex) #类直接点类体代码的函数属性,在子类中重用父类功能,就是一个普通的函数 self.stu_id=stu_id #子类派生出自己独有的数据属性 def choose_course(self): #子类派生出自己独有的数据属性 print(‘%s is choosing course‘ %self.name) class OldboyTeacher(OldboyPeople): def __init__(self, name, age, sex, level): OldboyPeople.__init__(self,name,age,sex) #子类重用父类中的方法 self.level=level #子类中派生出自己独有的属性 def score(self,stu,num): #子类派生出自己独有的函数属性 stu.score=num print(‘老师[%s]为学生[%s]打分[%s]‘ %(self.name,stu.name,num)) # 创造课程----------------------------------对象 python=Course(‘python全栈开发‘,‘5mons‘,3000) #调用课程对象,产生课程对象,并自动触发__init__函数的执行 linux=Course(‘linux运维‘,‘5mons‘,800) # python.tell_info() #课程对象直接绑定课程类下的方法,并将课程对象当做第一个对象自动传入 # linux.tell_info() # 创造学生与老师-----------------------------对象 stu1=OldboyStudent(‘猪哥‘,19,‘male‘,1) tea1=OldboyTeacher(‘egon‘,18,‘male‘,10) # 重点 # 将学生、老师与课程对象关联/组合-------------将对象之间进行关联 # --------------------------关键----------------------------------------------- stu1.course=python #---------------将学生对象stu1与课程对象python关联 tea1.course=linux #---------------将老师对象stu1与课程对象linux关联 # --------------------------关键----------------------------------------------- ‘‘‘组合就是一个类的对象具备某一个属性,该属性的值是指向另外一个类的对象‘‘‘ # 即学生类产生的学生对象具备课程的属性,该课程的属性值是指向课程类中的课程对象的 stu1.course.tell_info() #--------------等价于python.tell_info(),会打印出学生的课程信息 tea1.course.tell_info() #--------------等价于linux.tell_info(),会打印出老师的课程信息
二、菱形继承问题
#coding:utf-8 ‘‘‘ 1、菱形继承 当一个子继承多个父类时,多个父类最终继承了同一个类,称之为菱形继承 2、菱形继承的问题: python2区分经典类与新式类,如果子的继承是一个菱形继承,那么经典类与形式的区别为? 经典类下查找属性:深度优先查找-----------------一条道走到黑 新式类下查找属性:广度优先查找------------------最后才去找菱形的端点 ‘‘‘ class G(object): # def test(self): # print(‘from G‘) pass class E(G): # def test(self): # print(‘from E‘) pass class B(E): # def test(self): # print(‘from B‘) pass class F(G): # def test(self): # print(‘from F‘) pass class C(F): # def test(self): # print(‘from C‘) pass class D(G): # def test(self): # print(‘from D‘) pass class A(B,C,D): def test(self): print(‘from A‘) # pass obj=A() #C3算法只试用新式类,经典类不适用 print(A.mro()) #mro是一种C3算法,[<class ‘__main__.A‘>, <class ‘__main__.B‘>, <class ‘__main__.E‘>, <class ‘__main__.C‘>, <class ‘__main__.F‘>, <class ‘__main__.D‘>, <class ‘__main__.G‘>, <class ‘object‘>] obj.test() #A->B->E-C-F-D->G-object-------对象属性的查找会严格按照mro列表的顺序进行查找
三、在子类派生的新方法中重用父类功能的另种方式
# 在子派生的新方法中重用父类功能的两种方式 # 方式一:与继承无关 #指名道姓法,直接用:类名.函数名 class OldboyPeople: school = ‘oldboy‘ def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class OldboyStudent(OldboyPeople): def __init__(self,name,age,sex,stu_id): OldboyPeople.__init__(self,name,age,sex) #-------(减少代码冗余)指名道姓法,直接用:类名.函数名,按照函数传参的规则进行传参即可 self.stu_id=stu_id #子类派生出自己独有的数据属性 def choose_course(self): #子类派生出自己的函数属性 print(‘%s is choosing course‘ %self.name) # 方式二:严格以mro列表继承属性查找关系 # super()会得到一个特殊的对象,该对象就是专门用来访问父类中的属性的(按照继承的关系) # super().__init__(不用为self传值)------------可以理解为super()是一个特殊的对象,所以对象绑定方法有一个自动传值的效果 # 注意: # super的完整用法是super(自己的类名,self),在python2中需要写完整,而python3中可以简写为super() class OldboyPeople: school = ‘oldboy‘ def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class OldboyStudent(OldboyPeople): # 定制学生类的数据属性,在定制数据属性的过程中,重用了父类中的数据属性 def __init__(self,name,age,sex,stu_id): # OldboyPeople.__init__(self,name,age,sex) #------父类功能重用方法一 super(OldboyStudent,self).__init__(name,age,sex) #------父类功能重用方法二 self.stu_id=stu_id #定制学生类的函数属性 def choose_course(self): print(‘%s is choosing course‘ %self.name) stu1=OldboyStudent(‘猪哥‘,19,‘male‘,1) print(stu1.__dict__) #-------查看学生对象的字典属性,{‘name‘: ‘猪哥‘, ‘age‘: 19, ‘sex‘: ‘male‘, ‘stu_id‘: 1} print(OldboyStudent.mro()) #------查看学生类的继承关系,[<class ‘__main__.OldboyStudent‘>, <class ‘__main__.OldboyPeople‘>, <class ‘object‘>] # 继承顺序查找再应用: class A: def f1(self): print(‘A.f1‘) class B: def f2(self): super().f1() #B类和A类没有继承关系,但是会按照mro列表,从该类的下一个类继续进行查找,即此时会到A中进行查找 print(‘B.f2‘) class C(B,A): pass obj=C() print(C.mro()) #C-》B->A->object,查看C类的继承关系,[<class ‘__main__.C‘>, <class ‘__main__.B‘>, <class ‘__main__.A‘>, <class ‘object‘>] obj.f2() #对象属性的查找会严格按照mro列表的顺序进行查找,自己的对象没有到自己的类中找,自己的类中没有,到父类中找,此时父类查找的先后顺序就是按照mro列表来的 # 打印结果: ‘‘‘ A.f1 B.f2 ‘‘‘
四、多态与多态性
‘‘‘ 1 什么是多态 多态指的是同一种事物的多种形态 水-》冰、水蒸气、液态水 动物-》人、狗、猪 2 为和要用多态 多态性: 继承同一个类的多个子类中有相同的方法名 那么子类产生的对象就可以不用考虑具体的类型而直接调用功能 3 如何用 ‘‘‘ import abc class Animal(metaclass=abc.ABCMeta): #定义一个抽象类,规范一个类的类 @abc.abstractmethod #装饰器装饰后,意味着但凡继承类该类的方法,函数属性的属性名都必须与父类的函数属性名一致,否则就会报错 def speak(self): pass @abc.abstractmethod def eat(self): pass # Animal() #强调:父类是用来制定标准的,不能被实例化-------此时实例化就会报错,这并不是python崇尚的,python更多的是一种约定俗成的,而不是硬性的限制 class People(Animal): def speak(self): print(‘say hello‘) def eat(self): pass class Dog(Animal): def speak(self): print(‘汪汪汪‘) def eat(self): pass class Pig(Animal): def speak(self): print(‘哼哼哼‘) def eat(self): pass peo1=People() dog1=Dog() pig1=Pig() # #继承同一个动物类的多个子类(人、狗、猪类)中有相同的方法名(speak\eat),那么子类产生的对象就可以不用考虑具体的类型而直接调用功能 peo1.speak() #不用考虑具体的对象类型,而直接调用speak的功能 dog1.speak() pig1.speak() # -----------------------不用考虑是什么动物来调用speak的函数属性,所以将其封装成一个功能----------------------------------- def my_speak(animal): animal.speak() my_speak(peo1) my_speak(dog1) my_speak(pig1) # -----------------------不用考虑是什么动物来调用speak的函数属性,所以将其封装成一个功能----------------------------------- # 不同的数据类型,他们都有统计长度的这个方法,所以我们想到的是将他们制定成一套方法,便于对不同的数据类型进行统计 l=[1,2,3] s=‘helllo‘ t=(1,2,3) print(l.__len__()) #用同一种形式去调用的好处就是将其功能封装成一个函数时,只需要传入对象就可以了 print(s.__len__()) #如果用不同的方法名去统计不同数据类型的长度,这样封装成函数时就需要制定不同的函数去封装 print(t.__len__()) # def len(obj): # return obj.__len__() print(len(l)) # l.__len__() print(len(s)) #s.__len__() print(len(t)) # python推崇的是鸭子类型,只要你叫的声音像鸭子,并且你走路的样子也像鸭子,那你就是鸭子 class Disk: def read(self): print(‘disk read‘) def write(self): print(‘disk wirte‘) class Process: def read(self): print(‘process read‘) def write(self): print(‘process wirte‘) class File: def read(self): print(‘file read‘) def write(self): print(‘file wirte‘) obj1=Disk() obj2=Process() obj3=File() obj1.read() obj1.write()
原文地址:https://www.cnblogs.com/sui776265233/p/9234603.html
时间: 2024-11-09 20:46:26