今日所学:
一、组合
当类之间有显著不同,并且较小的类是较大的类所需的组件时,常用组合。
class School: def __init__(self,name,addr): self.name=name self.addr=addr class Course: def __init__(self,type,price,school): self.type=type self.price=price self.school=school class Teacher: def __init__(self,name,school,course): self.name=name self.school=school self.course=course s1=School("清华大学","南校区") s2=School("清华大学","北校区") s3=School("清华大学","东校区") s4=School("清华大学","西校区") c1=Course("python","10000",s1) c2=Course("linux","20000",s2) c3=Course("java","40000",s3) c4=Course("C+","30000",s4) t1=Teacher("happy",s1,c2) t2=Teacher("banana",s2,c1) t3=Teacher("alex",s3,c4) t4=Teacher("alvin",s4,c3) msg=‘‘‘ 1 清华大学 南校区 2 清华大学 北校区 3 清华大学 西校区 4 清华大学 东校区 ‘‘‘ while True: print(msg) menu={"1":s1,"2":s2,"3":s3,"4":s4} choice=input("请输入序号:>> ") school_obj=menu[choice] type_obj=input("请输入课程名:>> ") price_obj=input("请输入价钱:>> ") new_course = Course(type_obj, price_obj, school_obj) print("你的学校在[%s],你的课程名字为[%s]" %(new_course.school.name,new_course.type)) teacher_name=input("请输入老师名字:>> ") new_teacher=Teacher(teacher_name,school_obj,type_obj) print("你的课程是[%s],你的老师是[%s]" %(new_course.type,new_teacher.name)) break
二、继承
当类之间有很多相同的功能,提取这些共同的功能作为基类,常用继承
1、继承有两种含义:
(1)继承基类的方法,并做出自己的改变或扩展(不常用)
class Father: money=123 def __init__(self,name): print("我是你爸爸") self.name=name def hit_son(self): print("%s打他的儿子" %self.name) class Son(Father): #继承:在子类的函数名后加个父辈的名字 money=1234354654 print(Father.__dict__) print(Son.__dict__) print(Son.money) #输出为子类的money,即当子类和父类定义重名时,子类会先在自己的属性里面找,找不到再去父类里找。 f1=Father("alex") Father.hit_son(f1) Son.hit_son(f1) #子类可以调用父类的数据属性和函数属性 >>> {‘__module__‘: ‘__main__‘, ‘money‘: 123, ‘__init__‘: <function Father.__init__ at 0x000002C56949B4C0>, ‘hit_son‘: <function Father.hit_son at 0x000002C56949B550>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘Father‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Father‘ objects>, ‘__doc__‘: None} {‘__module__‘: ‘__main__‘, ‘money‘: 1234354654, ‘__doc__‘: None} 1234354654 我是你爸爸 alex打他的儿子 alex打他的儿子
(2)接口继承:声明某个子类兼容于基类。定义一个接口类,子类继承接口类,并且实现接口中定义的方法(归一化继承)
import abc #在接口继承中需引进该模块 class All_files(metaclass=abc.ABCMeta): @abc.abstractmethod #需加入一个装饰器 def read(self): #在接口类继承中的方法不用实现逻辑,且不需要实例化,仅为规范 pass @abc.abstractmethod def write(self): pass class Disk(All_files): def read(self): print("disk read") def write(self): print("disk write") class Cdrom(All_files): def read(self): print("cdrom read") def write(self): print("cdrom write") class Mon(All_files): def read(self): print("mon read") def write(self): print("mon write") d1=Disk() d1.write() d1.read() >>> disk write disk read
注意:
1、接口类继承实质上是要求做一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关系具体细节,可一视同仁的处理实现了特定接口的所有对象。这在程序设计中成为归一化设计。
2、归一化使得高层的外部使用者可以不加区分地处理所有接口兼容的对象集合。
三、多类继承顺序
1、多类继承顺序有两种:
新式类:基类或父类继承了object类,则为新式类,否则为经典类。
python2有经典类也有新式类,python3中只有新式类
#继承顺序 #新式类:广度优先 #经典类:深度优先 class A: def test(self): print("A") class B(A): def test(self): print("B") class C(A): def test(self): print("C") class D(B): def test(self): print("D") class E(C): def test(self): print("E") class F(D,E): def test(self): print("F") f1=F() f1.test() #继承顺序:F-->D-->B-->E-->C-->A #Python中全为新式类,继承顺序也为广度优先 print(F.__mro__) #在定义好类后,python会自动生成一个mro列表,表中列明了继承的顺序,mro列表是通过一个C3线性化算法实现的。 >>> F (<class ‘__main__.F‘>, <class ‘__main__.D‘>, <class ‘__main__.B‘>, <class ‘__main__.E‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘object‘>)
2、广度优先遵循三天原则:
(1)子类会先于父类被检查;
(2)多个父类会根据他们在列表中的顺序被检查;
(3)如果对下一类存在两个合法的选择,则会选择第一个父类。
四、子类调用父类的方法
有三种方法
import abc class Vehicle(metaclass=abc.ABCMeta): country="China" @abc.abstractmethod def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power @abc.abstractmethod def run(self): print("%s准备开动啦" %self.name) class Subway(Vehicle): def __init__(self,name,speed,load,power): # Vehicle.__init__(self,name,speed,load,power) super().__init__(name,speed,load,power) #这里三种方式都可以,但常用super的方法,不用传入self。 # super(Subway,self).__init__(name,speed,load,power) def run(self,name): super().run() def tell_info(self,name,speed,load,power): print("%s %s %s %s" %(self.name,self.speed,self.load,self.power)) s1=Subway("广州一号线","10km/s","10000","电") s1.run("广州一号线") s1.tell_info("广州一号线","10km/s","10000","电") >>> 广州一号线准备开动啦 广州一号线 10km/s 10000 电
注意:只有在对象调用类属性或者实例化时python才会自动传入self参数,在接口继承中则没有。
super方法有两个好处:(1)不用写父类名;(2)不用传入self
以上。
Python 小栈_18:Python 面向对象之组合、继承
原文:https://www.cnblogs.com/211293dlam/p/12555612.html