6 面向对象
介绍
一、特性:
-
class
-
object
封装、继承、多态
二、语法:
属性、方法、构造函数、析构函数
私有方法,私有属性
类变量
实例
面向过程 VS 面向对象
1.1编程范式
编程是 程序 员 用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 , 一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式有很多种不同的方式, 对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式。 不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路, 大多数语言只支持一种编程范式,当然也有些语言可以同时支持多种编程范式。 两种最重要的编程范式分别是面向过程编程和面向对象编程。
面向过程编程(Procedural Programming) Procedural programming uses a list of instructions to tell the computer what to do step-by-step. 面向过程编程依赖 - 你猜到了- procedures,一个procedure包含一组要被进行计算的步骤, 面向过程又被称为top-down languages, 就是程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题 。基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决。
举个典型的面向过程的例子, 数据库备份, 分三步,连接数据库,备份数据库,测试备份文件可用性。
1.2面向对象编程
OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
面向对象的几个核心特性如下
Class 类 一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法
Object 对象 一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同
Encapsulation 封装 在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法
Inheritance 继承 一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
Polymorphism 多态 多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。 编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。 对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。 多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定
代码:
class Names: def __init__(self,name): self.name = name def bulk(self): print("%s: ha ha ha!" % self.name) n1 = Names("张三") n2 = Names("李四") n3 = Names("王五") n1.bulk() n2.bulk() n3.bulk()
实例
演示oop编程的好处:
class Role(object): def __init__(self, name, role, weapon, life_value=100, money=15000): #构造函数 #在实例化是做一些类的初始化的工作 self.name = name self.role = role self.weapon = weapon self.life_value = life_value self.money = money def shot(self): print("shooting...") def got_shot(self): print("%s ah...,I got shot..." % self.name) def buy_gun(self, gun_name): print("%s just bought %s" % (self.name,gun_name)) r1 = Role('Alex', 'police', 'AK47') #生成一个角色(把一个类变成一个具体对象的过程叫 实例化(初始化一个类,造了一个对象) ) r1.got_shot() r1.buy_gun("AK47") r2 = Role('Jack', 'terrorist', 'B22') #生成一个角色 r2.got_shot() #Role.got_shot(r2) #r2 传给 self
函数调用 --》 执行 --》 返回结果
r1 = Role.__init__() return x123123
类:
r1 = Role( r1, "张三", "police", "15000" )
r1.name = "张三"
r1.role = "police"
r1.money = 15000
r1.buygun() # Role.buy_gun(r1)
实例变量和类变量
类变量的用途,公用的属性,节省开销
class Role(object): n = "123" n_list = [] name = "我是类name" def __init__(self, name, role, weapon, life_value=100, money=15000): #构造函数 #在实例化是做一些类的初始化的工作 self.name = name self.role = role self.weapon = weapon self.life_value = life_value self.money = money def shot(self): print("shooting...") def got_shot(self): print("%s ah...,I got shot..." % self.name) def buy_gun(self, gun_name): print("%s just bought %s" % (self.name,gun_name)) # print(Role.n) r1 = Role('zhangsan', 'police', 'AK47') #生成一个角色(把一个类变成一个具体对象的过程叫 实例化(初始化一个类,造了一个对象) ) r1.name = "张三" r1.n_list.append("from r1") r1.bullet_prove = True # print(r1.weapon) # del r1.weapon # print(r1.n,r1.name,r1.bullet_prove,r1.weapon) r1.n = "改类变量" #实例变量,与Role.n的变量没关系,优先级:实例变量>类变量 print(r1.n,Role.n) Role.n = "ABC" r2 = Role('Jack', 'terrorist', 'B22') #生成一个角色 r2.name = "李四" r2.n_list.append("from r2") #给类变量添加元素 print("r2.n_list.append(from r2): ",r2.n_list,Role.n_list) r2.n_list = ["123","456"] print("r2.n_list = [123,456]: ",r2.n_list,Role.n_list) r2.n_list.append("from r2") #给实例变量添加元素 print("r2.n_list = [123,456]: ",r2.n_list,Role.n_list) r2.n = "我是r2.n" print(r2.n,r2.name,Role.n,r2.n_list,Role.n_list,r1.n_list) #r2.n为先找实例变量,没有再找类变量;Role.n直接找类变量 print(r1.n,r2.n)
r2.n_list.append("from r2")
实例变量r2.n_list存在才添加元素,否则给类变量r2.n_list添加元素
析构函数
在实例释放、销毁的时候自动执行的,通常用于做一些收尾工作,如关闭一些数据库连接,打开的临时文件。
私有方法、私有属性
class Role(object): def __init__(self, name, role, weapon, life_value=100, money=15000): #构造函数 #在实例化是做一些类的初始化的工作 self.name = name self.role = role self.weapon = weapon self.__life_value = life_value #私有属性,在函数内使用 self.money = money def __del__(self): pass #print("%s 彻底死了。" %self.name) def show_status(self): self.__life_value -= 50 print("name:%s weapon:%s life_val:%s" %(self.name,self.weapon,self.__life_value)) def __show_weapon(self): #私有方法 pass def shot(self): print("shooting...") def got_shot(self): print("%s ah...,I got shot..." % self.name) def buy_gun(self, gun_name): print("%s just bought %s" % (self.name,gun_name)) r1 = Role('张三', 'police', 'AK47') #生成一个角色(把一个类变成一个具体对象的过程叫 实例化(初始化一个类,造了一个对象) ) r1.got_shot() r1.buy_gun("AK47") r1.show_status() # del r1 # r2 = Role('Jack', 'terrorist', 'B22') #生成一个角色 # r2.got_shot() #Role.got_shot(r2) #r2 传给 self
类的继承
class People: def __init__(self,name,age): self.name = name self.age = age def eat(self): print("%s is eating..." %self.name) def talk(self): print("%s is talking..." %self.name) def sleep(self): print("%s is sleeping..." %self.name) class Man(People): def piao(self): print("%s is piaoing..." %self.name) def sleep(self): People.sleep(self) #继承父级 print("man is sleeping") class Woman(People): def get_birth(self): print("%s is born a baby..." % self.name) m1 = Man("zhangsan",18) m1.eat() #调用父级类方法 m1.piao() m1.sleep() w1 = Woman("zhangsan",26) w1.get_birth()
类的继承2
# class People: #经典类 class People(object): #新式类 def __init__(self,name,age): self.name = name self.age = age self.friends = [] def eat(self): print("%s is eating..." %self.name) def talk(self): print("%s is talking..." %self.name) def sleep(self): print("%s is sleeping..." %self.name) class Relation(object): # def __init__(self,n1,n2): #测试代码 # print(self.name) def make_friends(self,obj): #w1 print("%s is making friends with %s" % (self.name,obj.name)) #obj.name = w1.name self.friends.append(obj) # self.friends.append(obj.name) # obj.name会写死 ## class Man(People,Relation): # def __init__(self,name,age,money): #继承父类,添加属性 # # People.__init__(self,name,age) # super(Man,self).__init__(name,age) #super方法(新式类写法)(People类名有改动不影响) # self.money = money # print("%s 一出生就有%s money" %(self.name,self.money)) def piao(self): print("%s is piaoing..." %self.name) def sleep(self): People.sleep(self) #继承父级 print("man is sleeping") class Woman(People): def get_birth(self): print("%s is born a baby..." % self.name) m1 = Man("zhangsan",18 ) w1 = Woman("lisi",26 ) m1.make_friends(w1) w1.name = "小明" print(m1.friends[0].name) # print(m1.friends[0]) #obj.name会写死 ##
多继承,继承第一个就不会继承第二个
py2 经典类是按深度优先,新式类是按广度优先来继承的
py3 经典类和新式类都是统一按广度优先来继承的
class A: def __init__(self): print("A") class B(A): pass # def __init__(self): # print("B") class C(A): def __init__(self): print("C") class D(B,C): pass # def __init__(self): # print("D") obj = D() # #D>B>C>A
继承实例:学校
class School(object): def __init__(self,name,addr): self.name = name self.addr = addr self.students = [] self.staffs = [] def enroll(self,stu_obj): print("为学员%s 办理注册手续" %stu_obj.name) self.staffs.append(stu_obj) def hire(self,staff_obj): self.staffs.append(staff_obj) print("雇佣新员工%s " % staff_obj.name) class SchoolMember(object): def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def tell(self): pass class Teacher(SchoolMember): def __init__(self,name,age,sex,salary,course): super(Teacher,self).__init__(name,age,sex) self.salary = salary self.course = course def tell(self): print(""" ----- info of Teacher:%s ----- Name:%s Age:%s Sex:%s Salary:%s Course:%s """%(self.name,self.name,self.age,self.sex,self.salary,self.course)) def teach(self): print("%s is teaching course [%s]" %(self.name,self.course)) class Student(SchoolMember): def __init__(self,name,age,sex,stu_id,grade): super(Student,self).__init__(name,age,sex) self.stu_id = stu_id self.grade = grade def tell(self): print(""" ----- info of Student:%s ----- Name:%s Age:%s Sex:%s Stu_id:%s Grade:%s """%(self.name,self.name,self.age,self.sex,self.stu_id,self.grade)) def pay_tuition(self,amount): print("%s has paid tution for $%s" % (self.name,amount) ) school = School("XX学院","地球") t1 = Teacher("张三", 55, "M", 20000,"Linux") t2 = Teacher("李四",20,"M",5000,"PythonDevOps") s1 = Student("王五",36,"M",1001,"PythonDevOps") s2 = Student("赵六",18,"M",1002,"Linux") t1.tell() s1.tell() school.hire(t1) school.enroll(s1) school.enroll(s2) print(school.students) print(school.staffs) school.staffs[0].teach() for stu in school.students: stu.pay_tuition(5000)
多态
class Animal: def __init__(self,name): self.name = name def talk(self): pass #raise NotImplementedError("") @staticmethod def animal_talk(obj): obj.talk() class Cat(Animal): def talk(self): print('abc') class Dog(Animal): def talk(self): print("der") # def animal_talk2(obj): # obj.talk() d = Dog("张三") # d.talk() c = Cat("李四") # c.talk() Animal.animal_talk(d) Animal.animal_talk(c) # animal_talk2(d)