1.面向对象简单介绍,在学习面向对象的时候,我们会学习到以下内容:
特性:class、object;封装,继承,多态
语法:属性,方法,构造函数,析构函数,私有方法,私有属性,类变量,实例变量
2.面向对象特性介绍:
(1)类:class
一个类就是对一类拥有相同属性的对象的抽象、蓝图、原型;在类中定义了这些对象都具备的属性、共同方法。
(2)object对象:一个对象就是一个类的实例化后的实例。
(3)Encapsulation 封装:
在类中对数据的赋值、内部调用,对外部对象是透明的;使类变成容器,包含类的数据和方法。
(4)Tnheritance 继承:
一个类可以派生出子类,在父类定义的属性、方法自动被子类继承。
(5)Polymoyphism 多态:
同一个基类派生出不同子类,每个子类在继承同样方法名的同时对父类方法做了不同的实现。
3.通过例子来看一下opp编程
(1)我们现在来看一个关于狗吠的例子:
class Dog: def __init__(self,name): self.name = name def bulk(self): print("%s:wang wang wang!" % self.name) d1=Dog("一") d2=Dog("二") d3=Dog("三") d1.bulk() d2.bulk() d3.bulk()
(2)下面我们通过cs游戏中创建两个角色,给这两个角色赋予不同的属性和方法,使其实现不同的功能。
class Role: #Role为类名 def __init__(self, name, role, weapon, life_value=100, money=15000): #构造函数 #在实例化时做一些类的初始化的工作 self.name = name #self.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("ah...,I got shot...") def buy_gun(self, gun_name): print("%s just bought %s" % (self.name,gun_name)) r1 = Role('wu', 'police','AK47') #生成一个角色,相当于Role(r1,'Alex', 'police','AK47')
#实例化:初始化一个类,相当于造了一个对象;把一个类变成一个具体对象的过程为实例化 r2 = Role('Jack', 'terrorist', 'B22') # 生成一个角色;r2又叫为Role的实例 r1.buy_gun("b51") #内部实际是Role.buy_gun(r1) 类Role中的self接受的实际是self方法
def __init__(self):是构造函数,作用:在实例化时做一些类的初始化的工作
在以上cs例子中,如果我们只定义了类跟方法,没有实例化、没有调用,那么类在函数中也是存在的,可以通过打印类名来验证一下
def buy_gun(self, gun_name): print("%s just bought %s" % (self.name,gun_name)) print(Role) #函数没有调用,但是在内存中是存在的
输出结果为 <class '__main__.Role'>
实际上,r1 = Role('wu', 'police','AK47')实例化时,我们将r1一起传入内存中,所以这里我们实例化时实际是r1=Role(r1,'Alex', 'police','AK47')
如r1.buy_gun("b51") ,内部实际是Role.buy_gun(r1) ,类Role中的self接受的实际是self方法
got_shot、buy_gun等方法使保存在类的属性中的,需要的时候调用即可。
4.实例变量与类变量
(1)我们还是以cs游戏来说明实例变量与类变量。
在构造函数中,self.name=name,为实例变量,self.name赋给了实例,为实例变量(静态属性),作用域就是实例本身;
类变量不在构造函数中,直接写在类Role下面;
def shot(self): #类的方法,即功能(动态属性)
r2 = Role('Jack', 'terrorist', 'B22') # 生成一个角色;实例化;r2又叫为Role的实例
(2)我们在类Role中定义类变量 n,并可打印
A.没有实例化对象,类变量可以打印
class Role: #Role为类名 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 print(Role.n) #类的变量存在类的内存中,还没有实例化便可以打印
B.实例化对象后,类变量仍然可打印
print(Role.n) r1 = Role('Alex', 'police', 'AK47') print(r1.n,r1.name) r2 = Role('Jack', 'terrorist', 'B22') print(r2.n,r2.name)
C.增加与实例变量相同的类变量,name="我是类name",发现输出结果与B中一样;这时得出结论:实例化时先找实例本身,如果实例本身没有,就去类里面找,比如n,在实例变量中没有,类变量里面有,就找到了n=123。
(3)实例变量与类变量的增删改
修改r1与r2的名字:
r1 = Role('Alex', 'police', 'AK47') r1.name="wu" #修改实例变量中的name print(r1.n,r1.name) r2 = Role('Jack', 'terrorist', 'B22') r2.name="徐" print(r2.n,r2.name)
在实例化后添加一个新的属性:
r1 = Role('Alex', 'police', 'AK47') r1.name="wu" #修改实例变量中的name r1.bullet_prove=True #添加一个新的属性,穿防弹衣 print(r1.n,r1.name,r1.bullet_prove) #先找实例本身,如果实例本身没有,就去类里面找;
#比如n,在实例变量中没有,类变量里面有,如果找到了n=123
在实例化后删除一个属性:
print(r1.weapon) del r1.weapon #删除一个属性 print(r1.weapon)
修改类变量n:其实r1.n是在r1内存中增加了一个变量n;改变的不是类变量,在r2中没有变量n,所以在r2中打印类变量,结果为123;
r1.n="改类变量" #其实是在r1的内存中 增加了一个变量n,n为“改类变量”;在这里改变的不是类变量 print("r1:",r1.weapon,r1.n)
print("r2:",r2.weapon,r2.n)
print(Role.n) #打印类变量中的n,输出结果仍为123
Role.n="ABC" #在实例化r1,r2后,修改类变量n的值,打印发现 r1.n为 改类变量;r2.n为 ABC
print(r1.n,r2.n)
在类变量中增加一个n的列表n_list:r2.n_list与Role.n_list输出结果一样,因为form r1与from r2都是保存在类的内存n_list
class Role: #Role为类名 n=123 #类变量 name="我是类name" n_list=[]
... ... r1 = Role('Alex', 'police', 'AK47') r1.n_list.append("from r1") r2 = Role('Jack', 'terrorist', 'B22') r2.n_list.append("from r2") print("r2:",r2.name,r2.n,r2.n_list) print(Role.n_list)
5.类变量的作用即析构函数
(1)类变量:大家共同的属性,节省了开销。
(2)析构函数:在实例释放/销毁时自动执行,通常用于收尾工作;比如关闭数据库连接、关闭打开的临时文件。
还是以cs游戏为例,在类Role中写一个析构函数:
#析构函数 def __del__(self): print("%s 完。。。。" % self.name)
我们现在来体验一下析构函数:
r1 = Role('Alex', 'police','AK47') r1.buy_gun("AK47") r1.got_shot() #程序退出时,会执行析构函数;所以在两个角色都运行完成后,才执行析构函数,退出 r2 = Role('Jack', 'terrorist', 'B22') r2.got_shot()
我们现在来看一下打印结果为:
Alex just bought AK47 ah...,I got shot... ah...,I got shot... Alex 完。。。。 Jack 完。。。。
对象、实例释放或销毁的时候自动执行;所以析构函数最后执行,是因为两个角色都运行完成后,程序退出,析构函数执行;
如果我们不想等到程序退出时执行析构函数,我们可以将r2实例化前删除r1
r1 = Role('Alex', 'police','AK47') r1.buy_gun("AK47") r1.got_shot() #程序退出时,会执行析构函数;所以在两个角色都运行完成后,才执行析构函数,退出 del r1 #如果删除角色r1的话,为销毁程序,所以销毁程序后,会执行析构函数 r2 = Role('Jack', 'terrorist', 'B22') r2.got_shot()
打印结果为:
Alex just bought AK47 ah...,I got shot... Alex 完。。。。 ah...,I got shot... Jack 完。。。。
6.私有方法与私有属性
私有属性一般分为动态属性(方法)跟静态属性(变量),一般认为私有属性就是变量。
(1)将构造函数中的变量修改为私有属性,在变量名前加__,这时外部无法访问
self.__life_value = life_value #'__life_value' 为私有属性,私有属性在内部可以访问跟修改,如在函数中修改,发现输出结果修改
如下,在访问是会报错,输出结果会报错“'Role' object has no attribute '__life_value'”
r1 = Role('Alex', 'police','AK47') print(r1.__life_value)
如果我们要访问私有属性,要在类Role中定义一个 show_status() 方法:
#定义访问私有属性的方法 def show_status(self): print("name:%s weapon:%s life_val:%s" %(self.name,self.weapon,self.__life_value))
这时便可以通过show_status方法来访问了:
r1 = Role('Alex', 'police','AK47') print(r1.show_status()) #访问私有属性
我们可以在内部对私有属性进行修改,在got_shot()属性中可以进行修改,这时再次通过show_status方法访问,发现life_value的值减少50
def got_shot(self): self.__life_value -=50 #私有变量 print("ah...,I got shot...")
(2)同样的,修改某个方法为私有方法也是一样,在函数名前面加__,
def __shot(self): #类的方法,即功能(动态属性) #加上__为私有方法,在外面无法访问,执行r1.__shot() 会报错 print("shooting11...")
在外面访问时会报错: 'Role' object has no attribute '__shot'
r1 = Role('Alex', 'police','AK47') r1.__shot() #__shot为私有方法,无法访问
这篇文章先写到这里,内容有点多,下次还是要分开写比较好,关于继承跟多态下一篇文章再会。