面对对象进阶
类的继承
python当中,父类和子类(派生类),父类和子类只有在继承的时候才会产生
继承是为了拿到父类的所有东西
class Parent_Foo: #父类 def __init__(self, first_name, money, car, house): self.first_name = first_name self.money = money * 0.5 print('继承财产扣掉一半') self.car = car self.house = house def find_wife(self): print(f'{self.first_name}先生找到妻子白富美')# pf = Parent_Foo('?', -1, 'tesla', '上海汤臣一品1栋')class Son_Foo(Parent_Foo): #子类 passsf = Son_Foo('?', 1000, 'tesla', '上海汤臣一品1栋') #子类继承父类的所有东西print(sf.first_name)print(sf.money)print(sf.car)print(sf.house)sf.find_wife()继承财产扣掉一半猪1000teslashanghai汤臣一品1栋猪先生找到妻子白富美
class Animal(): #父类 def __init__(self, height, weight): self.height = height self.weight = weight def jiao(self): print(self.__class__.__name__, '叫')class XingXing(): #父类 def sleep(self): print('睡觉')class People(Animal, XingXing): #子类 def read(self): #功能 print('read') def jiao(self): #类的功能 print('jiao')aobama = People(170, 120) aobama.jiao()aobama.sleep()meixi = People(168, 140)meixi.jiao()class Dog(Animal): def eat_shi(self): print('eat_shi')shinubi = Dog(40, 50)shinubi.jiao()jiao睡觉jiaoDog 叫
不推荐使用继承,当你继承多个的时候,功能与功能之间会混乱,顶多继承一个
继承后查找顺序:先自己,再类,在父类,再父类,在父类,在父类的父类
class Foo: #父类 def f1(self): print('Foo.f1') def f2(self): print('Foo.f2') self.f1()class Bar(Foo): #子类 def f1(self): print('Bar.f1')b = Bar()print(b.__dict__) #{}b.f2() #Foo.f2 Bar.f1
类的派生
类的派生:添加新的属性的同时还有继承父类的所有东西
派生:继承父类属性的同时增加新的属性,然后使用super().__init__()
class Animal(): def __init__(self, height, weight): # self给对象,self=peo,180,140 self.height = height # peo.height = 180 self.weight = weight # peo.weight = 140 def jiao(self): print(self.__class__.__name__, '叫')class XingXing(Animal): #继承 def __init__(self, gender,height, weight): super().__init__(height, weight) #继承上一个的参数 self.gender = gender def sleep(self): print('睡觉')class People(XingXing): #继承 def __init__(self,name,age,height,weight,gender): super().__init__(height,weight,gender) #继承上一个的参数 self.name = name self.age = age def read(self): print('read') def jiao(self): print('jiao')peo = People('nick',18,180,140,'male') #print(peo.__dict__)
类的组合
组合:组合在一起
# 简单的选课系统class People: #父类 人类 def __init__(self, name, gender): self.name = name self.gender = gender def eat(self): #技能: 吃 print(f'{self.name}开始吃了')class Student(People): #子类 学生 def __init__(self, student_id, name, gender): #属性特征 学号,姓名,性别 self.student_id = student_id super(Student, self).__init__(name, gender) def choose_course(self, course): # python对象 选择课程 课程类当参数传入 self.course = course # 组合 # 把对象当作变量值来用,当作形参/实参/返回值。 print(f'{self.name}选课{course.name}成功')class Teacher(People): #子集 教师 def __init__(self, level, name, gender): #属性 级别,性别 self.level = level super(Teacher, self).__init__(name, gender) #从人类中派生姓名,级别 def scored(self, student, course, score): #技能,评分 课程类当参数传入 print(f'老师{self.name}给{student.name}课程{course.name}打分{score}')class Course: #课程 一个类 def __init__(self, name, price): self.name = name self.price = priceclass Admin(People): #子类 管理员 def create_course(self, name, price): #属性 姓名,价格 course = Course(name, price) #调用了Course课程类 print(f'管理员{self.name}创建了课程{name}') return course# 课程# python = Course('Python', '8888')# linux = Course('Linux', '6666')# 学生zhubajie = Student('01', 'zhubajie', 'male')sunwukong = Student('02', 'sunwukong', 'male')# 老师nick = Teacher('1', 'nick', 'male')tank = Teacher('2', 'tank', 'female')# 管理员egon = Admin('egon', 'male')# 业务逻辑# 1. 创建课程python = egon.create_course('python', '8888') #管理员egon创建了课程pythonprint(python.__dict__) #{'name': 'python', 'price': '99999'}linux = egon.create_course('linux', '6666') #管理员egon创建了课程linuxprint(linux.__dict__) #{'name': 'linux', 'price': '66666'}# 2. 学生选择课程zhubajie.choose_course(python) #zhubajie选课python# 3. 老师给学生打分nick.scored(zhubajie,python,'0') #老师nick给zhubajie课程python打分0
菱形继承问题
在python2当中不会默认继承类,必须得子集手动添加
新式类:只要继承了object类的就是新式类,python3当中所有的类都是新式类
经典类:没有继承object类的就是经典类,只有python2当中有经典类
当即继承为菱形继承的时候,经典类和新式类搜索某一个属性的顺序会不一样
在新式类中,当遇到菱形继承时,会以广度优先查找
在经典类中,当遇到菱形继承时,会以深度优先查找
普通继承时,就是正常顺序找
class G: def text(self): print('from G')class F(G): def text(self): print('from F')class E(G): # def text(self): # print('from E') passclass D(G): def text(self): print('from D')class C(F): def text(self): print('from C')class B(E): # def text(self): # print('from B') passclass A(B,C,D): # def text(self): # print('from A') passa = A()a.text()for i in A.__mro__: print(i)from C
多态和对多态性
import abcclass Animal(metaclass=abc.ABCMeta): def __init__(self,height,weight): self.height = height self.weight = weight # @abc.abstractmethod def sleep(self): print('我在睡觉') @abc.abstractmethod def speak(self): print(self,'开始叫了') @abc.abstractmethod def eat(self): print(self,'开始吃了')class People(Animal): def speak(self): print('开始叫了') def eat(self): print(self,'开始吃了')class Dog(Animal): def speak(self): print('开始叫了') def eat(self): print(self,'开始吃了')class Cow(Animal): def speak(self): print('开始叫了') def eat(self): print(self,'开始吃了')peo = People(180,140)dog = Dog(50,100)cow = Cow(100,200)peo.speak()dog.sleep()cow.sleep()# sheep.speak()# mao.speak()peo.eat()dog.eat()
import abcclass Animal(metaclass=abc.ABCMeta): def __init__(self,height,weight): self.height = height self.weight = weight # @abc.abstractmethod def sleep(self): print('我在睡觉') @abc.abstractmethod def speak(self): #以animal为父类的子类中必须有speak,才可以运行 print(self,'开始叫了') @abc.abstractmethod def eat(self): #以animal为父类的子类中必须有eat,才可以运行 print(self,'开始吃了')class Foo(Animal): #定义动物类 def speak(self): #技能 讲话 没有eat技能 passf = Foo(1,1) #运行类,类属性赋值 身高,体重f.sleep() #运行父类中的技能报错,因为没有eat技能
鸭子类型:长的像鸭子,叫声也像鸭子,就是鸭子,(只要有speak和eat两种方法,那他就是动物类)
对于我们这个例子,你只要有speak/有eat方法,我无论你怎么定义这个类,你就是动物的一种形态,你这样才能用动物的方法,否则无法使用动物的方法