目录 面对对象编程的特点 继承 类的派生 类的组合 菱形继承问题 类的多态与多态性 面对对象编程的特点 继承 ? 在 OOP 程序设计中,当我们定义一个 class 的时候,可以从某个现有的c
目录
- 面对对象编程的特点
- 继承
- 类的派生
- 类的组合
- 菱形继承问题
- 类的多态与多态性
面对对象编程的特点
继承
? 在 OOP 程序设计中,当我们定义一个 class 的时候,可以从某个现有的class 继承,新的 class 称为子类(Subclass),而被继承的 class 称为基类、父类或超类(Base class、Super class)。Python当中,父类,子类(派生类),父类和子类只有在继承时才会产生。
? 继承的优点就是子类可以轻而易举获得父类的所有属性,即减少代码的重复。
#以Animal为父类,People为Animal的子类 class Animal(): def __init__(self, height, weight): self.height = height self.weight = weight class People(Animal): pass wq = People(170,140) print(wq.height,wq.weight) #170 140 #继承后,子类的属性查找先从子类的对象属性中找—子类的函数方法—父类—父类的父类 class Foo: def f1(self): print('Foo.f1') def f2(self): # self = b print('Foo.f2') self.f1() # b.f1() class Bar(Foo): def f1(self): print('Bar.f1') b = Bar() print(b.__dict__) # {} b.f2() # Foo.f2 # Bar.f1
?
类的派生
? 其实就是子类在继承父类所有的属性和函数方法时,自己拥有的独特的属性和方法,派生就是如何绑定这些独特的属性和函数方法。
#第一种方法:已经脱离了继承的本质,无需继承即可以获得父类的属性和函数方法 class Animal(): def __init__(self, height, weight): self.height = height self.weight = weight class People: def __init__(self.name,age,height,weight): Animal.__init__(self,height,weight) self.name = name self.age = age wq = People('wnagqiang,25,175,130') #第二种方法:必须通过继承父类 class Animal(): def __init__(self, height, weight): self.height = height self.weight = weight class People(Animal): def __init__(self.name,age,height,weight): super().__init__(height,weight) #其实是对第一种方法的数据封装 #super(People,self).__init__(height,weight) #python2中的写法 self.name = name self.age = age wq = People('wnagqiang,25,175,130') print(wq.__dict__) #可以通过报错获知属性个数
? 派生的和关键问题就是弄清楚对象属性的个数以及属性的查找
类的组合
#简单的选课系统 class People: def __init__(self,name,gender): self.name = name self.gender = gender class Student(People): def __init__(self,name,id,gender): super().__init__(name,gender) self.id = id def choose_course(self,course): **self.course = course** #即通过类的函数对象(引用、返回值,参数)达到类的组合效果 return '%s选课%s成功'%(self.name,course.name) class Teacher(People): def __init__(self,name,level,gender): super().__init__(name,gender) self.level = level def scored(self,student,course,score): return '%s老师给%s学生%s课程打分:%s'%(self.name,student.name,course.name,score) class Course: def __init__(self,name,price): self.name = name self.price = price class Admin(People): def create_course(self,name,price): course = Course(name,price) print('管理员%s创建课程%s'%(self.name,name)) return course #学生 s1 = Student('wangqiang','123','male') s2 = Student('liujin','124','female') #老师 t1 = Teacher('nick','0','female') #管理员 a1 = Admin('sb','eunuch') #业务逻辑 #1.创建课程 course1 = a1.create_course('python',20000) #管理员sb创建课程python course2 = a1.create_course('linux',18000) #管理员sb创建课程linux #2.学生选择课程 print(s1.choose_course(course1)) print(s2.choose_course(course2)) #3.老师打分 print(t1.scored(s1,course1,99)) #nick老师给wangqiang学生python课程打分:99
菱形继承问题
? 在python3当中会默认继承object类,新式类:只要继承了object类的就是新式类,python3当中所有的类都是新式类。
? 在python2当中不会默认继承object类,必须得自己手动添加,经典类:没有继承object类的就是经典类, 只有python2当中有经典类。
? 当继承为菱形继承的时候:在新式类中:当遇到菱形继承时,会以广度优先查找
? 在经典类中:当遇到菱形继承时,会以深度优先查找
类的多态与多态性
? 当子类和父类都存在相同的 run()方法时,我们说,子类的 run()覆盖了父类的 run(),在代码运行的时候,总是会调用子类的 run()。这样,我们就获得了继承的另一个好处:多态。
#鸭子类型:子类和父类中都有相同的函数名,当定义一个类的调用函数时,只需要传入类名即可,无需实例 class People: def sleep(self): print('p is sleeping!') class Animal: def run(self): print('animal is running!') class Dog(Animal): def run(self): print('dog is running!') class Cat(Animal): def run(self): print('cat is running!') #调用类的定义函数 def run_twice(self): self.run() #只需要传入类名()即可调用类中的函数方法 run_twice(Animal()) #animal is running! run_twice(Dog()) #dog is running! run_twice(Cat()) #cat is running!
?