Python3.5——面向对象编程
1、面向过程与面向对象的比较
(1)面向过程编程(procedural programming)
面向过程编程又被称为:top-down languages,程序从上到下 一步步执行,从头到尾的解决问题。
基本设计思路为:程序一开始是解决一个大问题,然后把大问题分解成多个小问题或子过程,这些小问题执行的时候再继续分解,
直到小问题足够简单到可以在一个小范围内解决。
缺点:若程序要进行修改,则修改的部分依赖的各个部分也要修改,这样会发生一连串的影响,随着程序越来越大,编程方式的维护难度也会越来越高。
所以,如果写一下简单的脚本,去做一些一次性的任务,用面向过程的方式是极好的,如果要处理的任务是复杂的,且需要不断迭代和维护的,还是用面向对象是最方便的。
(2)面向对象编程(oop)
面向对象编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述。
优点:可以使程序的维护和扩展变得简单,并且可以大大提高程序的开发效率;另外,基于对象的程序编程,可以让别人更加理解你的代码逻辑,是团队开发变得更加从容。
核心的特征:世界万物皆对象,世界万物皆可分类。
a、类(class)
类:是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象都具备的属性、共同的方法。
b、对象(object)
对象:类实例化后的实例,一个类必须经过实例化方能在程序中调用。
一个类可以实例化多个对象,每个对象可以有不同的属性。人类是指使用的人,每个人是指具体的对象。
c、封装(encapsulation)
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法。
d、继承(Inheritance)
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承。
e、多态(Polymorphism)
多态:是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,
且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现。
把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物,与不同的具体事物进行对话。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。
这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定。
2、面向对象编程
(1)无论什么形式的编程,都要明确一下原则:写重复的代码是非常不好的地级行为;之前写的代码需要不断的更新。
所以,开发的程序要遵循易读、易改的原则,即:可读性好、易扩展。
(2)示例代码:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#面向对象--CS游戏模拟
classRole(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
defshot(self):
print("shotting...")
defgot_shot(self):
print("ah...%s got shot..."%self.name)
defbuy_gun(self,gun_name):
print("%s just bought %s"%(self.name,gun_name))
r1 = Role("Jack","police","AK-47")#实例化(初始化一个类,创建了一个对象)
r1.buy_gun("B51")
r2 = Role("Amy","terrorist","B22")
r2.got_shot()
#运行结果:
Jack just bought B51
ah...Amy got shot...
注:
a、类的基本定义
第一句:定义一个类,class是定义类的语法,Role是类名,(object)是新式类的写法,必须这样写;
第二句:__init__()叫做初始化方法,也叫构造方法(虽然它是函数的形式,但在类中就不叫函数了,叫做方法),在类被调用时这个方法会自动执行,进行一些初始化动作,
所以__init__(self,name,role,weapon,life_value=100,money=15000)就是要在创建一个角色时给它设置这些属性。
b、实例化:把一个类变成一个具体的对象的过程叫实例化。
在这里,实例化生成一个角色,会自动把参数传给类Role下面的__init__(...)方法。
初始化一个角色,就需要调用这个类一次;上面的创建角色时,并没有给__init__(...)传值,是因为类在调用它自己的__init__(...)是自己帮你给self参数赋值了。
执行r1 = Role('liu','police','AK47’)时,python的解释器其实干了两件事:
1、 在内存中开辟一块空间指向r1这个变量名。
2、调用Role这个类并执行其中的__init__(…)方法,相当于Role.__init__(r1,'Jack','police',’AK47’),这么做是为什么呢?
是为了把'Jack','police',’AK47’这3个值跟刚开辟的r1关联起来,因为关联起来后,你就可以直接r1.name, r1.weapon 这样来调用。
所以,为实现这种关联,在调用__init__方法时,就必须把r1这个变量也传进去,否则__init__不知道要把那3个参数跟谁关联。
所以这个__init__(…)方法里的,self.name = name , self.role = role等等的意思就是要把这几个值 存到r1的内存空间里。
结:self就是示例本身,实例化时Python会自动把这个示例本身通过self参数传递进去。
r1.buy_gun("B51")===》Python会自动转换成:Role.buy_gun(r1,"B51”)
依然没给self传值 ,但Python还是会自动的帮你把r1 赋值给self这个参数, 为什么呢? 因为,你在buy_gun(..)方法中可能要访问r1的一些其它属性,
比如这里就访问 了r1的名字,怎么访问呢?你得告诉这个方法,于是就把r1传给了这个self参数,然后在buy_gun里调用 self.name 就相当于调用r1.name ,
如果还想知道r1的生命值 有多少,直接写成self.life_value就可以了。
总结:
a、上面的这个r1 = Role('Alex','police','AK47’)动作,叫做类的“实例化”, 就是把一个虚拟的抽象的类,通过这个动作,变成了一个具体的对象了, 这个对象就叫做实例。
b、刚才定义的这个类体现了面向对象的第一个基本特性,封装,其实就是使用构造方法将内容封装到某个具体对象中,然后通过对象直接或者self间接获取被封装的内容。
3、实例变量与类变量
(1)类变量:存在类的内存中,没有实例化即可使用;实例化后,通过实例也可调用类变量。作用:共用的属性,节省开销。
(2)实例变量:描述某个具体对象一些特定的属性,只能在实例本身中使用。
(3)区别:若一个类中,既有类变量name,又有实例变量name,则先找实例变量,实例变量没有的情况下,再找类变量。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#面向对象--CS游戏模拟
classRole(object):
n =123#类变量
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
defshot(self):#类的方法(功能)--动态属性
print("shotting...")
defgot_shot(self):
print("ah...%s got shot..."%self.name)
defbuy_gun(self,gun_name):
print("%s just bought %s"%(self.name,gun_name))
#r1是类Role的一个实例化对象
# 实例化就是以类Role为模板,在内存开辟一块空间,存上数据,赋值成一个变量名
#实例化(初始化一个类,创建了一个对象)
r1 = Role("Jack","police","AK-47")#此时self相当于r1,Role(r1,"Jack","police","AK-47")
r1.buy_gun("B51")#r1也被称作Role的一个实例
r1.name ="liu"#修改r1的实例变量
r1.n ="改变类变量"#在r1中修改类变量n的值,相当于创建一个n,不会影响r2
r1.bullet_prove =True#添加新的属性,只能在r1中使用
print(r1.n)
r2 = Role("Amy","terrorist","B22")#此时self相当于r2,Role(r2,"Amy","terrorist","B22")
r2.got_shot()
print(r2.n)
Role.n ="abc"#通过类名修改类变量的值
print("r1:",r1.n)
print("r2:",r2.n)
#运行结果:
liu just bought B51
改变类变量
ah...Amy got shot...
123
r1: 改变类变量
r2: abc
4、析构函数 def __del__(self):
作用:在实例销毁/释放时自动执行,通常用于做一些收尾工作,如:关闭一些数据库链接,关闭打开临时的文件。
析构函数的调用顺序与构造方法的调用顺序相反。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#面向对象--CS游戏模拟
classRole(object):
n =123#类变量
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):#析构函数
print("%s game over..."%self.name)
defshot(self):#类的方法(功能)--动态属性
print("shotting...")
defgot_shot(self):
print("ah...%s got shot..."%self.name)
defbuy_gun(self,gun_name):
print("%s just bought %s"%(self.name,gun_name))
r1 = Role("Jack","police","AK-47")
r1.buy_gun("AK47")
r1.got_shot()
r2 = Role("Amy","terrorist","B22")
r2.got_shot()
#运行结果:
Jack just bought AK47
ah...Jack got shot...
ah...Amy got shot...
Amy game over...
Jack game over...
5、私有方法、私有属性(变量) 在变量或者方法前面添加两个下划线 "__",即可变成私有方法、私有属性
私有属性只能在类的内部,通过self使用,在类的外部无法直接访问和修改其内容。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#面向对象--CS游戏模拟
classRole(object):
n =123#类变量
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):#析构函数
print("%s game over..."%self.name)
defshow_status(self):#私有属性只能在类的内部使用
print("name:%s weapon:%s life_val:%s"%(self.name,self.weapon,self.__life_value))
defshot(self):#类的方法(功能)--动态属性
print("shotting...")
defgot_shot(self):
self.__life_value -=50
print("ah...%s got shot..."%self.name)
defbuy_gun(self,gun_name):
print("%s just bought %s"%(self.name,gun_name))
r1 = Role("Jack","police","AK-47")
r1.buy_gun("AK47")
r1.got_shot()
r1.show_status()
#运行结果:
Jack just bought AK47
ah...Jack got shot...
name:Jack weapon:AK-47life_val:50
Jack game over...