初始面向对象之后,我们来学习面向对象的三大特性以及面向对象的其他补充方面的知识。
组合
组合只有一个例子因为组合只作为上一章的补充内容
#老师 课程 生日 class Course: def __init__(self,name,period,price): self.name = name self.period = period self.price = price class Birth: def __init__(self,year,month,day): self.year = year self.month = month self.day = day class Teacher: def __init__(self,name,salary,boy_friend,python): self.name = name self.salary = salary self.bf = boy_friend self.course = python python = Course('python','6 months',20000) egg = Teacher('egon',200,'yuan',python) print(egg.bf) print(egg.name) print(egg.course.name) egg_birth = Birth(1965,2,2) print(egg_birth.year) egg.birth = egg_birth print('***',egg.birth.year) 组合
继承
定义:继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又叫做基类或超类,新建的类被称为派生类或子类。
python中类的继承可以分为单继承和多继承
查看继承的方法是_base_ #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
注:如果没有指定基类,python中的类会默认继承object类,object类是所有类的基类,并且提供了一些常见方法,如(_str_)的实现
优点:解决代码重用的问题,减少代码冗余
继承解决的问题:什么是什么(类与类之间的关系)
组合:是一种什么有什么的关系,也是为了减少重复代码。
实例一 class Animal: def eat(self): print('eating') def drink(self): print('drink') class Cat(Animal): #继承了Animal类 def __init__(self,name): self.name=name self.breed='猫' def cry(self): print('喵喵叫') class Dog(Animal): def __init__(self,name): self.name=name self.breed='狗' def wang(self): print('汪汪叫') a1=Cat('加菲猫') print(a1.name) a1.eat() b1=Dog('汪汪狗') print(b1.name) b1.drink() class Person: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def walk(self): print('%s is walk'%self.name) 实例二 class Teacher(Person): def __init__(self,name,age,sex,salary): Person.__init__(self,name,age,sex) self.salary=salary def teacher(self): print('%s is teacher'%self.name) def foo(self): Person.foo(self) print('from teacher') class Student(Person): def __init__(self,name,age,sex,group): Person.__init__(self,name,age,sex) self.group=group def study(self): #定义了Student类的study方法 print('%s is study'%self.name) t=Teacher('egon',35,'male',1000) print(t.name) t.walk() t1=Student('小明',18,'male','老男孩') t1.study()
一、 继承与抽象
抽象即抽取类似或者说比较像的部分。
继承:是基于抽象的结果,通过编程语言去实现它,肯定肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
二、 派生
派生指的是子类可以添加自己的新属性或者重新定义这些属性(不会影响到父类),但需要注意的是一旦定义的自己的属性名与父类的属性名相同时,那么在调用新增的属性时,就用自己的。
class Animal: def __init__(self,name,aggr,life_value): self.name=name self.aggr=aggr self.life_value=life_value def eat(self): print('%s is eating'%self.name) class Dog(Animal): def bite(self,people): ''' 派生:狗有咬人的功能 ''' people.life_value-=self.aggr class Person(Animal): '''人类继承了Animal''' def attack(self,dog): ''' 派生:人有攻击的技能 ''' dog.life_value-=self.aggr egg=Person('egon',100,5000) ha2=Dog('二愣子',20,1000) print(ha2.life_value) egg.attack(ha2) print(ha2.life_value)
三、 抽象类和接口类
抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。
抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计
在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念。
1、多继承问题
在继承抽象类的过程中,我们应该尽量避免多继承;
而在继承接口的时候,我们反而鼓励你来多继承接口
2、抽象类方法的实现
(1)在抽象类中,我们可以对一些抽象方法做出基础实现;
from abc import ABCMeta,abstractclassmethod class Animal(metaclass=ABCMeta): @abstractclassmethod def eat(self): print('打开袋子') print('放个碗') print('把粮食倒在碗里') def sleep(self): pass class Dog(Animal): super().eat() def eat(self): print('dog is eating') def sleep(self): print('dog is sleeping') d=Dog() d.eat()
抽象: 从小范围到大范围
(2)而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
from abc import ABCMeta,abstractmethod class Payment(metaclass = ABCMeta): #metaclass --> 元类 @abstractmethod def pay(self,money):pass class Applepay(Payment): def pay(self,money): print('apple pay 支付了%s'%money) class Alipay(Payment): def pay(self,money): print('支付宝 支付了%s'%money) class Wechatpay(Payment): def fuqian(self,money): print('微信支付了%s'%money) def payment(pay_obj,money): pay_obj.pay(money) apple1 = Applepay() ali1 = Alipay() wechat1 = Wechatpay() payment(wechat1,200)
注:#接口类
#约束继承接口类的子类必须实现被abstractclassmethod装饰的方法
#在接口类中不要不要做实现
#接口类不能被实例化
(3)总结
当几个子类的父类,有相同的功能,就用抽象类
当几个子类 有相同的功能 但实现各不相同的时候就用接口类
抽象类和接口类的本质作用:约束
钻石继承
继承顺序
python如果继承了多个类寻找方法有两个方法深度优先(经典类)和广度优先(新式类),而python3中没有经典类了,所以我们不用考虑多重情况。
新式类:广度优先
经典类:深度优先