面向对象
特性 class object
封装、继承、多态
语法:属性、方法
构造函数(在实例化时做一些类的初始化的工作 该函数是用于传参数)
析构函数(在实例释放、销毁的时候自动执行的、通常用于一些收尾工作,如:关闭一些数据库链接,关闭打开的临时文件 当程序执行完以后, 析构__del__(self)自动进行内存销毁,或者在程序执行中,如果要销毁一个实例时,手动通过 del r1就会删掉变量名,然后析构函数就会自动销毁内存 )
私有方法(函数)、 私有属性(变量) 私有:表示只能自己访问,别人不能访问
私有属性:就是通过self.__life_value =life_value 添加两个下划线 就会将该变量隐藏,外面访问不了,只有在类中才可以改变 给类中函数添加两个__就会变成私有方法
类变量(大家共用属性,节省开销 不需要复制多个)、实例变量(表示具体对象的每个属性)
1 class person():
2 cn ="中国"
3 """与下面的cn ="china"功能相同,但是 类变量cn ="中国"
4 只需要在类中复制一份就可以,但是cn="china"有几个人需要
5 实例化就需要复制几分到每个人所定义的内存中去,就要消耗很多内存"""
6 def __init__(self,name,sex,age,job,cn ="china"):
7 self.name =''
8 pass
面向对象编程
OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
面向对象的几个核心特性如下
Class 类
一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法
Object 对象
一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同
Encapsulation 封装
在类中对数据的赋值、内部调用对外部用户是不可见的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法
Inheritance 继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
Polymorphism 多态
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定
无论用什么形式来编程,我们都要明确记住以下原则:
1、写重复代码是非常不好的低级行为
2、你写的代码需要经常变更
类的基本知识(私有方法、构造函数、析构函数)
1 class Role(object):
2 n =123 #这个变量称为类变量 存在于类的内存里 不实例化类也能使用 通过 role.n
3 n_list=[]
4 """如果在Role中有一个列表,通过r1.n_list.append("from r1")
5 和r1.n_list.append("from r1") 再打印r1.n_list,或者r2.n_list,
6 或者Role.n_list 最后的结果都是 ['from r1', 'from r2']
7 因为都是通过append()追加,它们的变量名相同,也就是内存地址也是同一个,
8 故而结果相同
9 """
10 name ="类中name"
11 def __init__(self, name, role, weapon, life_value=100, money=15000):
12 """ self 就是为了存储下面的r1变量,下面的变量就为局部变量
13 名字叫:构造函数 内存中的东西在不用的情况下,会清除,所以通过赋给一个变量,那么就一直不会清除,在实例化时做一些类的初始化的工作 该函数是用于传参数
14 """
15 self.name = name #该值是赋给了实例 故而:该变量称之为实例变量(静态属性) 作用域就是实力本身
16 self.role = role
17 self.weapon = weapon
18 self.__life_value = life_value # 加个__就会变成私有属性
19 self.money = money
20
21 def shot(self):#其他函数调用类role的时候,仍然用到的是r1这个变量
22 print("shooting...")
23
24 def __del__(self): #析构函数 当程序执行完后执行该函数,
25 # 或者中途通过del r1就会直接删除r1变量名,然后析构函数就会直接销毁内存
26 print("%s:彻底死掉……" %self.name)
27 # def got_shot(self):
28 # print("ah...,I got shot...")
29 def got_shot(self):#谁调用got_shot 谁就是参数self
30 print("%s:ah...,I got shot..." % self.name )# r1.name 等价于self.name
31 def buy_gun(self, gun_name):#这三个函数都称之为类的方法(动态属性)
32 print("just bought %s" % gun_name)
33
34 r1 = Role('Alex', 'police', 'AK47') #把一个类变成一个具体对象的过程的实例化(初始化一个类,造了一个对象)
35 r1.name ="zhangsan"#可以再次赋值修改变量
36 r1.bullet_protect=True#添加新的属性 但是r2没有这个属性,因为只给r1添加了
37 r1.n ='改变变量' #并不是将类变量改变,而是在实例中直接生成了一个n这个变量的值,根据变量查找范围,先查找实例化的变量所以n会发生变化
38 r1.n_list.append("from r1")
39 #print(r1.weapon)
40 #del r1.weapon #删掉了r1的这个属性 对r2没有什么影响
41 r2 = Role('Jack', 'terrorist', 'B22') #生成一个角色 实例化成一个对象也叫role类的实例
42 r1.got_shot() # 有class内部转成了role.got_gun(r2) 故而 等价于:role.got_shot()
43 r2.n_list.append("from r2")
44 print(r1.n,r1.name,r1.bullet_protect)#在实例化后,找一个变量之后,会从实例变量开始查找,然后再从类变量中找
45
46 print(r2.name,r2.weapon,r2.n)
47 Role.n ="abc"
48 print(r1.n,r2.n_list)# 运行结果:改变变量 abc 只对r2有影响,对r1没有影响 因为r1自己有值
49 print(Role.n_list)
类的继承
1 #class People:# 经典类
2 class People(object):#新式类的写法
3 def __init__(self,name,age):
4 self.name =name
5 self.age =age
6 self.friends =[]
7 def eat(self):
8 print("%s is eating ……"%self.name)
9 def sleep(self):
10 print("%s is sleeping……"%self.name)
11 def talk(self):
12 print("%s is talking……"%self.name)
13 class Relation():
14 def make_friends(self,obj):#obj就是对象,就是将其与前面的谁调用make_friends有关联
15 print("%s make friends with %s"%(self.name,obj.name))
16 self.friends.append(obj) #即使改名字,这里也会跟着变化,这里是添加了关系
17 class Man(People,Relation): #两个字类之间不能相互继承 即Man不能和Woman相互继承 因为两者本来就不是同一所以才产生两个类
18 def __init__(self,name,age,money): #首先要将父类中的参数写入其中,并且将要添加的参数也写入其中
19 # People.__init__(self,name,age) # 将People中的构造函数应用到Man中 还是执行父类中的方法
20 super(Man,self).__init__(name,age)#等价于People.__init__(self,name,age) 万一以后将继承父类改了名字,只需要改上那个父类名就可以
21 self.money =money #对man中添加的值进行初始化 Woman中没有该参数
22 print("%s have %s yuan money" %(self.name,self.money))
23
24 def smoke(self):
25 print("%s is smoking……"%self.name)
26 def sleep(self): #在子类中修改父类中的方法
27 #People.sleep(self) #经典类的写法
28 super(Man, self).sleep()#等价于上面 新式类的写法
29 print("Man is sleep……")
30 def play_bastball(self):
31 print("%s is playing bastball……"%self.name)
32
33 class Woman(Relation,People):#多继承,是从左向右逐步进行,如果第一个已经将参数接收过来,第二个类直接使用即可,如果第一个没有将参数接收,第二个接受了参数,那么在没有接受第二个类之前就运行了第一个类,那也就 将报错
34 def birth(self):
35 print("%s is born the baby……"%self.name)
36 def wash(self):
37 print("%s is washing……"%self.name)
38
39 m1 =Man("zhangsan",26,100)
40 # m1.sleep()
41 # m1.talk()
42 #m1 =Man("zhangsan",26)
43 # m1.money= "10元"
44 # print(m1.money,m1.sleep,m1.talk)
45 w1 =Woman("hehua",28)
46 # w1.wash()
47 # w1 .birth()
48 m1.make_friends(w1)
49 w1.name ="wangwu"
50 print(m1.friends[0].name) #通过实验可知:obj将两者联系起来了
51 print(m1.friends[0]) #如果前面的self.friends.append(obj.name)那么
52 # m1和w1就会失去联系,此时只是对应一个字符串
经典类和新式类继承顺序问题
新式类 class A(object): 经典类 class A:
在如下中的继承中,对于继承中构造函数的执行__init__(self):
在python2.x中经典类是按深度优先来进行的,新式类是按广度优先来继承的
在python3.x中经典类和新式类都是统一按照广度优先来继承的