【python自动化第六篇:面向对象】
知识点概览:
- 面向对象的介绍
- 面向对象的特性(class,object)实例变量,类变量
- 面型对象编程的介绍
- 其他概念
编程范式:面向对象,面向过程,函数式编程
- 面向过程:通过一组指令告诉机器去一步一做什么;一个过程包含一组要被进行计算的步骤,从头到尾的执行顺序;程序的修改要注意各个部分的依赖关系,否则会影响其他过程的运行,发生一连串的影响,维护困难。
- 面向对象:OOP编程是利用类和对象来创建各种模型实现对真实世界的描述;使用面向对象编程的原因是一方面它会使得程序的维护和拓展变得比较简单,并且提高开发效率。使得代码更加清晰便于理解。
-
- 世界万物,皆可分类;世间万物,皆为对象
- 只要是说:对象就属于某种类
- 只要是对象,就肯定有属性
-
二、特性:
- class类:就是对异类拥有相同属性的对象的抽象、蓝图、以及原型。在这个类中定义了这些对象都具备的属性、共同的方法
- object对象:一个对象是类实例化后的实例,一个类必须要经过实例化之后才能在程序中得以调用
三大特性:
- 封装:在类中对数据赋值、内部调用对外部用户是透明的,这使得类变成了一个胶囊或者容器,里面包含着类的数据和方法
- 继承:一个类可以派生出自雷,在这个弗雷里定义的属性,方法自动被子类继承
- 多态:简单而言就是“有一个接口,多种实现”,指的是在一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做出了不同的实现,这就是同一种食物表现出多种形态
三、面向对象编程
- 类的开始
1
2
3
4
5
6
7
8
|
#!/usr/bin/env python # -*- coding:utf-8 -*- class Dog( object ): #定义类 def bulk( self ): #定义属性(方法) print ( "hehe wang wang wang !" ) d1 = Dog() #将类实例化 d1.bulk() #调用bulk方法 |
- 射击游戏模拟角色(深入类)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#!/usr/bin/env python # -*- coding:utf-8 -*- class Role( object ): #定义一个类 m = 123 #定义类变量 def __init__( self ,name,role,weapon,life_value = 100 ,money = 12000 ): #构造函数:在实例化时做一些类的初始化工作 self .name = name #给实例赋值(传参数),实例变量的作用域就是实例本身;实例变量也叫作静态属性 self .role = role self .weapon = weapon self .life_value = life_value self .money = money def shot( self ): #定义类的方法(功能),也可以成为动态属性 print ( "shot。。。。" ) def got_shot( self ): print ( 'i got shot....' ) def buy_gun( self ,gun_name): print ( "%s buy gun %s" % ( self .name,gun_name)) r1 = Role( "wanghui" , 'police' , 'kii' ) #实例化(初始化一个类,相当于造一个的对象):把一个类变成一个具体对象的过程 r1.buy_gun( 'ssdsd' ) |
- 类变量和实例变量(1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#!/usr/bin/env python # -*- coding:utf-8 -*- class Role( object ): n = 1234 #类变量 n_list = [] name = "类变量" def __init__( self ,name,role,weapon,life_value = 100 ,money = 12000 ): self .name = name #实例变量 self .role = role self .weapon = weapon self .life_value = life_value self .money = money def shot( self ): print ( "shoting!!!" ) def got_shot( self ): print ( "%s got shot!!" % self .name) def buy_gun( self ,gun_name): print ( "%s bought gun %s" % ( self .name,gun_name)) r1 = Role( 'wanghui' , 'police' , "ak99" ) r2 = Role( "lijie" , "jiji" , 'kb132' ) r1.name = '李连杰' #修改类变量 r1.bullet_prove = True #添加类变量 r1.n = "change_value" r1.n_list.append( 124 ) r2.n_list.append( 2 ) del r1.weapon #删除类变量 print (r1.n,r2.n) print (Role.n_list,r1.n_list,r2.n_list) #互相包含list print (r1.n,r1.name,r1.n_list,r1.bullet_prove) #找的结果还是从实例变量里面去找,如果实例本身不存在找类变量 |
- 类变量和实例变量(2)
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#!/usr/bin/env python # -*- coding:utf-8 -*- class Person( object ): cn = "中国" def __init__( self ,name,age,addr): self .name = name self .age = age self .addr = addr p1 = Person( "hah" , 18 , "huhhu" ) #类变量的作用:大家共用的属性,节省空间 |
- 三大特性:
- 封装:把不需要让别人看到的方法隐藏起来,使用"__"做前缀,
私有化的过程中也实现了封装,表示不想让别人访问
私有属性:自能被自己对应的实例访问,若果要被访问到,特点是在属性前面加__,那就得在定义一个函数,然后调用就可以得到私有属性了
私有方法:只有自己才能被访问得到,不能被外部访问,特点也是在方法名前面加__
- 封装:把不需要让别人看到的方法隐藏起来,使用"__"做前缀,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class Role( object ): n = 1234 #类变量 def __init__( self ,name,role,weapon,life_value = 100 ,money = 12000 ): self .name = name #实例变量 self .role = role self .weapon = weapon self .__life_value = life_value #属性私有化步骤(加__) self .money = money def show_status( self ): print ( "name:%s weapon:%s life_var:%s " % ( self .name, self .weapon, self .__life_value)) def __shot( self ): #私有方法(还是前面加__) print ( "shoting!!!" ) def got_shot( self ): self .__life_value - = 50 #私有属性在类的方法里面是可以修改的 print ( "%s got shot!!" % self .name) def buy_gun( self ,gun_name): print ( "%s bought gun %s" % ( self .name,gun_name)) r1 = Role( 'wanghui' , 'police' , "ak99" ) r2 = Role( "lijie" , "jiji" , 'kb132' ) #print(r1.__life_value) #私有属性不能被打印 r1.show_status() #这就可以调用私有属性了,现在是满血 r1.got_shot() #这会儿调用了中枪的方法,然后私有属性值会改变 r1.show_status() #私有属性life_value自然会减少50 |
-
- 继承:减少重复代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
#!/usr/bin/env python # -*- coding:utf-8 -*- class People( object ): def __init__( self ,name,age): self .name = name self .age = age def eat( self ): print ( "%s is eating" % self .name) def sleep( self ): print ( "%s is sleeping!!" % self .name) class Man(People): #继承父类People def drink( self ): print ( "%s is drinking!!" % self .name) def sleep( self ): #父类方法重构(子类和父类有同样的方法时就需要重构) People.sleep( self ) #这样也能执行父类的方法 print ( "man is sleeping!" ) class Woman(People): #不能调用兄弟类里的方法 def get_birth( self ): print ( "%s is bon a baby" % self .name) m1 = Man( "hahaha" , 23 ) m1.eat() m1.drink() m1.sleep() w1 = Woman( "bububu" , 24 ) w1.get_birth() |
-
- 多态:目的是为了实现接口的重复利用,同样也能做到节省代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
#!/usr/bin/env python # -*- coding:utf-8 -*- # 多态: class Animal( object ): def __init__( self ,name): self .name = name def talk( self ): pass @staticmethod #静态方法 def animal__talk(obj): # 创建新函数 obj.talk() class Dog(Animal): def talk( self ): print ( "wang wang!!" ) class Cat(Animal): def talk( self ): print ( "miao miao!!" ) d1 = Dog( "hhhh" ) c1 = Cat( 'loo' ) # d1.talk() #普通实现 # c1.talk() Animal.animal__talk(d1) #多态语法:实现了对Animal接口的重用 Animal.animal__talk(c1) |
四、其他概念
- 父类函数的重构问题:如果在继承的时候子类和父类的实例化参数有重复,则调用子类的实例化后的函数时,要注意父类函数的重构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#!/usr/bin/env python # -*- coding:utf-8 -*- class People( object ): def __init__( self ,name,age): self .name = name self .age = age def eat( self ): print ( "%s is eating" % self .name) def sleep( self ): print ( "%s is sleeping!!" % self .name) class Man(People): def __init__( self ,name,age,money): #重构了父类的构造函数,因此需要将父类的构造函数也要写上 super (Man, self ).__init__(name,age) #继承父类的构造方法 self .money = money #初始化自己的参数 print ( "%s has %s money" % ( self .name, self .money)) def drink( self ): print ( "%s is drinking!!" % self .name) p1 = People( "nimeiya" , 33 ) m1 = Man( "hehe" , 12 , 100 ) m1.drink() |
-
析构函数:在实例释放或者销毁的时候执行的,通常用于做一些收尾工作的,关闭一些数据库连接打开的临时文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
class Role( object ): n = 1234 #类变量 def __del__( self ): #析构函数:在对象或者实例销毁或者释放之后才会执行 print ( "%s 彻底死了 !!" % self .name) def __init__( self ,name,role,weapon,life_value = 100 ,money = 12000 ): self .name = name #实例变量 self .role = role self .weapon = weapon self .life_value = life_value self .money = money def shot( self ): print ( "shoting!!!" ) def got_shot( self ): print ( "%s got shot!!" % self .name) def buy_gun( self ,gun_name): print ( "%s bought gun %s" % ( self .name,gun_name)) r1 = Role( 'wanghui' , 'police' , "ak99" ) r2 = Role( "lijie" , "jiji" , 'kb132' ) r1.buy_gun( "gege" ) del r1 #这个实例被销毁了 ,那析构函数就开始执行了,然而之后才执行r2.got_shot(),因为还是要看销毁啊,只要有销毁就有析构函数的执行 r2.got_shot() |
-
新式类和经典类的区别在于:(object)
在Python2.x的经典类中是按照深度优先来继承的,然而在其新式类中用的是广度优先来继承的
在Python3.x中无论是经典类还是新式类都是按照广度优先来继承的 - 多继承问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
#!/usr/bin/env python # -*- coding:utf-8 -*- 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 sleep( self ): print ( "%s is sleeping!!" % self .name) class Relation( object ): def __init__( self ): print ( self .name) def make_friends( self ,obj): print ( "%s make friends with %s" % ( self .name,obj.name)) #name是从w1里面传过来的 self .friends.append(obj) class Man(People,Relation): #多继承 def drink( self ): print ( "%s is drinking!!" % self .name) def sleep( self ): #父类方法重构(子类和父类有同样的方法时就需要重构) People.sleep( self ) #这样也能执行父类的方法 print ( "man is sleeping!" ) class Woman(People,Relation): #多继承 def get_birth( self ): print ( "%s is bon a baby" % self .name) m1 = Man( "wanghui" , 24 ) w1 = Woman( "hehe" , 22 ) w1.name = "呵呵哒" #改名字 m1.make_friends(w1) #多继承调用 print (m1.friends[ 0 ].name) #打印列表内容 |
- 拓展(基本的关系拓展)
#!/usr/bin/env python # -*- coding:utf-8 -*- class School(object): #定义学校类 def __init__(self,school,addr): #构造函数 self.school = school #实例传参 self.addr = addr self.students = [] self.tearchers = [] self.stuffs = [] def enrool(self,stu_obj): #定义类的方法 self.students.append(stu_obj) print("请为学员%s办理注册"%stu_obj.name) def hire(self,stuffs_obj): print("请为员工%s办理入职"%stuffs_obj.name) self.stuffs.append(stuffs_obj) 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 teach %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交学费%s"%(self.name,amount)) school = School("清华大学","五道口") t1 = Teacher("呵呵",55,"M",90000,"Technology") #实例化过程 t2 = Teacher("biubiu",44,"F",80000,"Science") s1 = Student("你妹",23,"F",11030,"grade:1") s2 = Student("你大爷",33,"M",11031,"grade:2") t1.tell() #调用 s1.tell() school.enrool(s1) school.hire(t1) school.stuffs[0].teach() for stu in school.students: stu.pay_tuition(1000)