面向对象编程(类):
编程范式:不同的编程范式特点进行归纳总结得出来的编程方式类别。
编程:特定的语法+数据结构+算法组成的代码,使计算机执行任务。
程序:得到结果而编写一组指令的集合。
编程范式主要分为:面向过程编程、面向对象编程、函数式编程
面向过程编程:程序一步步从上到下执行。解决问题思路,把问题逐渐划分为小模块或子程序,从而继续划分。
面向对象编程(OOP):利用类和对象来创建各种模型实现对真实世界的描述,便于维护和扩展。
面向对象特性:
Class 类:一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型(模板)。在类中定义了这些对象的都具备的属性
(variables(data))、共同的方法。
Object 对象:一个类必须经过实例化后,方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,
就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同。
Encapsulation 封装:在类中对数据的赋值、内部调用对外部用户是不可见的,这使类变成了一个胶囊或容器,里面包含着类
的数据和方法。
Inheritance 继承:一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承。
Polynorphism 多态:多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,
且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。对不同类的对
象发出相同的消息将会有不同的行为。多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用
的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定。
面对对象语法:
class Dog:#定义一个类Dog def __init__(self,name):#传入名字,self.name,传入参数,构造函数 self.name=name def bulk(self): print('%s:wang wang wang!'%self.name) #定义类下的对象 dog1=Dog(name='yangjian') #调用方法 dog1.bulk()
实例化:把一个类变成具体对象的过程叫做实例化。
实例变量用途:储存实例的特有属性
类变量用途:储存类的共同属性,省内存
面向对象编程实例2:
class Role(object): #Role类名 class_variable=22344#类变量,存在类的内存里 name='mary' 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 #__init_()开辟一个内存,保存其中的值 def __del__(self):#析构函数,不能传参数,实例释放或删除时自动执行,不需要调用 print('实例释放') def __shot(self):#类的方法,(动态属性)#私有方法 print("shooting...") def show_states(self): print('name:%s ,life_value:%s'%(self.name,self.__life_value)) self.__shot()#调用私有方法 def got_shot(self): print("ah...,I got shot...") def buy_gun(self, gun_name): print("just bought %s" % gun_name) print(Role.class_variable)#类变量不需要实例化就可以打印,已存在 r1 = Role('zhaoyun', 'police', 'AK47') #生成一个角色,实例化(初始化一个类),把一个类变成具体对象的过程叫做实例化,r1称为Role的实例 r2 = Role('nvbu', 'terrorist', 'B22') #生成一个角色#相当于r2=Role(r2,'Jack','terrorist','B22') r1.got_shot()#相当于Role.got_shot(r1) r1.buy_gun('AK47')#相当于Role.buy_gun(r1,'AK47') print(r1.name)#查找实例变量时,优先从实例内存里找,找不到时再从类内存里找 r1.name='zhizhang'#修改实例变量 print(r1.name)#查找实例变量时,优先从实例内存里找,找不到时再从类内存里找 print(r1.class_variable)#实例中也可以找到类变量 r1.body_armor=100#添加实例变量 print(r1.body_armor) del r1.body_armor#删除实例变量 r1.class_variable='change self'#在实例中添加或修改一个变量 Role.class_variable='change'#修改类变量 print(r1.class_variable,'---',r2.class_variable) #print(r1.__life_value)不能调用和打印 r1.show_states()
析构函数:在实例释放或销毁时自动执行,通常用于通常用于做一些收尾工作,如关闭一些数据库链接、关闭打开的文件
私有方法:def __shot(self):pass 类方法前加两个下划线,变为私有方法,私有方法外部不能直接访问,类内部可以访问,
self.__private_methods内部调用
私有属性(变量):self.__life_value,实例变量两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。
封装:通过私有属性和私有方法封装.封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者
对象操作,对不可信的进行信息隐藏。
继承:作用是省代码。如果子类重写了__init__ 时,实例化子类,就不会调用父类已经定义的 __init__。相同方法,优先调用子类,
父类不起作用。
如果重写了__init__ 时,要继承父类的构造方法,可以使用 super 关键字:
super(子类,self).__init__(参数1,参数2,....)
还有一种经典写法:
父类名称.__init__(self,参数1,参数2,...)
继承顺序:pyhon3广度优先,优先找调用子类,然后父类,再查找上一级父类
在python2上,经典类为深度优先,一路查找到底;新式类为广度优先。
继承实例:
#class Books:#经典类 class Books(object):#定义父类,新式类:多继承方式与经典类不同 def __init__(self,total_page_number,book_name):#父类构造函数,初始化 self.pnum = total_page_number self.name = book_name print('test call') def writing(self): print('half of %s page has been writing'%self.pnum) def read(self): print('Today I read %s'%self.name) class Knowledge_carrier(object): def __init__(self,carrier_type,total_page_number): self.carrier=carrier_type self.pnum = total_page_number def iscarrier(self,carrier): if self.carrier==carrier: print(True) else: print('other carrier') def writing(self): print('all of %s page has been writing'%self.pnum) class Music_book(Books):#继承,括号内填父类的名字 def __init__(self,total_page_number,book_name,music_type):#子类初始化,此时父类的初始化无效 super(Music_book, self).__init__(total_page_number,book_name) self.music_type = music_type def writing(self):#方法和属性优先在子类中寻找,子类与父类存在相同时,调用子类方法。 #Books.writing(self)#调用父类的方法,经典类写法 super(Music_book, self).writing()#作用与上同,新式类写法 print('quarter of %s page has been writing'%self.pnum) def play(self): print('play the %s music,remain half of %s pages'%(self.music_type,self.pnum)) class Tech_book(Books):#继承,括号内填父类的名字 def __init__(self,total_page_number,book_name,tech_type):#重构子类,需要加上所有的参数,包括调用的父类参数 super(Tech_book, self).__init__(total_page_number,book_name)#=books.__init__() self.tech_type=tech_type def make(self): print('An %s invention was made'%self.tech_type) book1=Music_book(100,'piano_book','piano') book1.play() book1.read() book1.writing() book2=Tech_book(200,'A Brief History Of Time','Physics') book2.writing() book2.make() book2.read() print(book2.tech_type) #多继承 class NewMusicBook(Knowledge_carrier,Books,):#继承,括号内填父类的名字,多继承 def __init__(self,total_page_number,book_name,music_type,carrier_type):#子类初始化,此时父类的初始化无效 #super(NewMusicBook, self).__init__(total_page_number,book_name,carrier_type) Books.__init__(self,total_page_number,book_name) Knowledge_carrier.__init__(self,carrier_type,total_page_number) self.music_type = music_type def writing(self):#方法和属性优先在子类中寻找,子类与父类存在相同时,调用子类方法。 #books.writing(self)#调用父类的方法,经典类写法 super(NewMusicBook, self).writing()#作用与上同,新式类写法 print('quarter of %s page has been writing'%self.pnum) def play(self): print('play the %s music,remain half of %s pages'%(self.music_type,self.pnum)) NewBook=NewMusicBook(300,'songs','classic','electric') NewBook.writing()#多继承时调用父类方法,优先调用括号里父类从左往右含有的第一个 NewBook.read() NewBook.play() NewBook.iscarrier('paper')
1 class School(object): 2 def __init__(self,name,addr): 3 self.name=name 4 self.addr=addr 5 self.staffs=[] 6 self.students=[] 7 def enroll(self,stu_obj): 8 print('为学员%s办理注册手续'%stu_obj.name) 9 self.students.append(stu_obj) 10 def hire(self,staff_obj): 11 self.staffs.append(staff_obj) 12 print('雇佣新员工%s'%staff_obj.name) 13 class SchoolMember(object): 14 def __init__(self,name,age,sex): 15 self.name=name 16 self.age=age 17 self.sex=sex 18 def school_card(self): 19 print('Hello, %s. You can use the campus card to spend'%self.name) 20 class Teacher(SchoolMember): 21 def __init__(self,name,age,sex,salary,course): 22 super(Teacher,self).__init__(name,age,sex) 23 self.salary=salary 24 self.course=course 25 def tell(self): 26 print(''' 27 -----info of teacher %s------ 28 name:%s 29 age:%s 30 sex:%s 31 salary:%s 32 course:%s 33 '''%(self.name,self.name,self.age,self.sex,self.salary,self.course) 34 ) 35 def teach(self): 36 print('%s is teaching course [%s]'%(self.name,self.course)) 37 class Student(SchoolMember): 38 def __init__(self,name,age,sex,stu_id,grade): 39 super(Student, self).__init__(name,age,sex) 40 self.stu_id=stu_id 41 self.grade=grade 42 def tell(self): 43 print(''' 44 -----info of student %s------ 45 name:%s 46 age:%s 47 sex:%s 48 stu_id:%s 49 grade:%s 50 '''%(self.name,self.name,self.age,self.sex,self.stu_id,self.grade) 51 ) 52 def pay_tuition(self,amout,teacher): 53 print('%s has paid %s¥ tuition for course [%s] ' 54 %(self.name,amout,teacher.course)) 55 school=School('XiaMen university','XiaMem') 56 t1=Teacher('tusong',40,'M','20000','Chemistry') 57 t2=Teacher('xugou',30,'F',30000,'economics') 58 s1=Student('wangdasha',23,'M',1234144,2013) 59 s2=Student('guodong',23,'M',2345613,2013) 60 school.hire(t1) 61 school.hire(t2) 62 school.enroll(s1) 63 school.enroll(s2) 64 t1.school_card() 65 t2.school_card() 66 s1.school_card() 67 s2.school_card() 68 t1.tell() 69 t1.teach() 70 s1.tell() 71 s1.pay_tuition(5000,t1) 72 t2.tell() 73 t2.teach() 74 s2.tell() 75 s2.pay_tuition(6000,t2) 76 print(school.staffs) 77 print(school.students) 78 for i in school.students: 79 i.pay_tuition(5000,t1)
多态:多态则是为了实现另一个目的——接口重用。允许将子类类型的指针赋值给父类类型的指针。一个接口,多种实现。
封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目 的——接口重用!
多态实例:
class Animal(object): def __init__(self, name): # Constructor of the class self.name = name def talk(self): # Abstract method, defined by convention only raise NotImplementedError("Subclass must implement abstract method") class Cat(Animal): def talk(self): print('%s: 喵喵喵!' % self.name) class Dog(Animal): def talk(self): print('%s: 汪!汪!汪!' % self.name) def func(obj): # 一个接口,多种形态 obj.talk() c1 = Cat('赵云') d1 = Dog('周瑜') func(c1) func(d1)
领域建模的三字经方法:找名词、加属性、连关系。