day7 面向对象编程
编程范式
编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程,一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式有很多种不同的方式, 对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式。 不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路, 大多数语言只支持一种编程范式,当然也有些语言可以同时支持多种编程范式。 两种最重要的编程范式分别是面向过程编程和面向对象编程
面向过程编程
面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题 。基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决。这样做的问题也是显而易见的,就是如果你要对程序进行修改,对你修改的那部分有依赖的各个部分你都也要跟着修改, 随着程序越来越大, 这种编程方式的维护难度会越来越高。 所以我们一般认为, 如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程的方式是极好的,但如果你要处理的任务是复杂的,且需要不断迭代和维护的, 那还是用面向对象最方便了。
示例:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#面向过程编程while True: if cpu利用率 > 90%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 硬盘使用空间 > 90%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 内存占用 > 80%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 |
函数式编程
将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
示例:

练习:在终端输出如下信息 小明,10岁,男,上山去砍柴
小明,10岁,男,开车去东北
小明,10岁,男,最爱大保健
老李,90岁,男,上山去砍柴
老李,90岁,男,开车去东北
老李,90岁,男,最爱大保健

|
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 -*-#-Author-Lian#函数式编程def firewood(name, age, gender): print("%s,%s岁,%s,上山去砍柴" %(name, age, gender))def drive(name, age, gender): print("%s,%s岁,%s,开车去东北" %(name, age, gender))def dbj(name, age, gender): print("%s,%s岁,%s,最爱大保健" %(name, age, gender))firewood('小明', 10, '男')drive('小明', 10, '男')dbj('小明', 10, '男')#小明,10岁,男,上山去砍柴#小明,10岁,男,开车去东北#小明,10岁,男,最爱大保健firewood('老李', 90, '男')drive('老李', 90, '男')dbj('老李', 90, '男')#老李,90岁,男,上山去砍柴#老李,90岁,男,开车去东北#老李,90岁,男,最爱大保健 |
面向对象编程
1、类、对象、实例
OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
示例:

练习:在终端输出如下信息 小明,10岁,男,上山去砍柴
小明,10岁,男,开车去东北
小明,10岁,男,最爱大保健
老李,90岁,男,上山去砍柴
老李,90岁,男,开车去东北
老李,90岁,男,最爱大保健

|
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
|
#!/usr/bin/env python# -*- coding:utf-8 -*-#-Author-Lian#面向对象class Foo: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender def firewood(self): print("%s,%s岁,%s,上山去砍柴" % (self.name, self.age, self.gender)) def drive(self): print("%s,%s岁,%s,开车去东北" % (self.name, self.age, self.gender)) def dbj(self): print("%s,%s岁,%s,最爱大保健" % (self.name, self.age, self.gender))xiaoming = Foo('小明', 10, '男')xiaoming.firewood()xiaoming.drive()xiaoming.dbj()#小明,10岁,男,上山去砍柴#小明,10岁,男,开车去东北#小明,10岁,男,最爱大保健laoli = Foo('老李', 90, '男')laoli.firewood()laoli.drive()laoli.dbj()#老李,90岁,男,上山去砍柴#老李,90岁,男,开车去东北#老李,90岁,男,最爱大保健 |
面向对象编程的主要作用也是使你的代码修改和扩展变的更容易,那么小白要问了,既然函数都能实现这个需求了,还要OOP干毛线用呢? 呵呵,说这话就像,古时候,人们打仗杀人都用刀,后来出来了枪,它的主要功能跟刀一样,也是杀人,然后小白就问,既然刀能杀人了,那还要枪干毛线,哈哈,显而易见,因为枪能更好更快更容易的杀人。函数编程与OOP的主要区别就是OOP可以使程序更加容易扩展和易更改。
上面的程序做个简单认识即可,下面我们通过写一个cs程序来对面向对象编程做进一步认识

|
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
37
38
39
40
|
#!/usr/bin/env python# -*- coding:utf-8 -*-#-Author-Lian#面向对象classclass Role(object): #定义一个类, class是定义类的语法,Role是类名,(object)是新式类的写法,暂且先记住 def __init__(self,name,role,weapon,life_value=100,money=15000):#初始化函数,在生成一个角色时要初始化的一些属性就填写在这里 self.name = name #__init__中的第一个参数self为实例名称 self.role = role self.weapon = weapon self.life_value = life_value self.money = money #__init__()叫做初始化方法(或构造方法), 在类被调用时,这个方法(虽然它是函数形式,但在类中就不叫函数了, 叫方法)会自动执行, # 进行一些初始化的动作 def shot(self): # 开了枪后要减子弹数 print("%s is shooting......."%(self.name)) def got_shot(self): # 中枪后要减血 print("ah.....%s:I got shot...."%(self.name)) def buy_gun(self,gun_name): # 检查钱够不够,买了枪后要扣钱 print("%s just bought %s "%(self.name,gun_name))#生成一个角色 , 会自动把参数传给Role下面的__init__(...)方法,这个过程叫做类的实例化,r1叫做类的实例r1 = Role('Alex','police',"AK47") #此时self 相当于 r1 , Role(r1,'Alex','police','AK47’)r2 = Role('Jack','terrorist',"B22") #此时self 相当于 r2 , Role(r2,'Jack','terrorist','B22’)print(r1,type(r1))print(r1.role)r1.shot()r1.got_shot()r1.buy_gun("DZT100")# <__main__.Role object at 0x005A5BF0> <class '__main__.Role'># police# Alex is shooting.......# ah.....Alex:I got shot....# Alex just bought DZT100 |
2、类变量和实例变量
类变量为大家都共有的变量,只加载在类内存当中,不会加载在每个实例里;举个栗子:创建14亿用户,大家国籍都是中国,如果不把国籍写到类变量中,而是写到实例变量默认参数中,则14亿个实例,每个都要加载国籍到内存当中,会占用大量内存,这就是为什么我们要了解类变量的意义
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#类变量和实例变量class Role(object): #定义一个类, class是定义类的语法 n = 123 #类变量 name = "类name" 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 = moneyr1 = Role('Alex','police',"AK47") #实例print(Role.n,r1.n)print(Role.name,r1.name)#123 123#类name Alex |
由上面程序可知,类变量对全局生效,输入类名可直接调用;当类变量与实例变量相同且同时存在的话,实例变量优先
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#实例变量class Role(object): #定义一个类, class是定义类的语法 n = 123 #类变量 name = "类name" 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 = moneyr1 = Role('Alex','police',"AK47") #实例r1.name="wupeiqi"r1.bullet= Trueprint(r1.name,r1.bullet)#wupeiqi True |
类进行实例化之后,还可以对实例变量重新赋值、增加变量
|
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
|
#类变量和实例变量class Role(object): #定义一个类, class是定义类的语法 n = 123 #类变量 name = "类name" 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 = moneyr1 = Role('Alex','police',"AK47") #实例r2 = Role('lzl','terrorist','B22')r1.n = "r1的123"print(r1.name,r1.n)print(r2.name,r2.n)# Alex r1的123# lzl 123Role.n = "Role的123"print(r1.name,r1.n)print(r2.name,r2.n)# Alex r1的123# lzl Role的123 |
执行上面的程序发现,赋值r1.n后只是影响到实例r1,对r2.n并没有任何影响,这是因为赋值的实例变量与类变量名一样时,并不会改变类变量中的值,只影响到当前实例;当重新赋值类变量时,r2也跟着改变;哈哈,此时你以为你都懂了,那让我们对上面的程序做个升级吧!!
|
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
|
#类变量和实例变量class Role(object): #定义一个类, class是定义类的语法 list = [] #定义一个列表类变量 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 = moneyr1 = Role('Alex','police',"AK47") #实例r2 = Role('lzl','terrorist','B22')print(Role.list) #此时list为空#[]r1.list.append("from r1")r2.list.append("from r2")print(r1.list)print(r2.list)#['from r1', 'from r2']# ['from r1', 'from r2']print(Role.list)# ['from r1', 'from r2'] |
从上面的程序可看出r1、r2改变了类变量;懒得解释了,自己理解吧O(∩_∩)O哈哈~
3、析构函数
在实例释放、销毁的时候执行,通常用于做一下收尾工作(如关闭数据连接)
|
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
|
#析构函数class Role(object): #定义一个类, class是定义类的语法 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 彻底死了"%self.name) def shot(self): # 开了枪后要减子弹数 print("%s is shooting......."%(self.name)) def got_shot(self): # 中枪后要减血 print("ah.....%s:I got shot...."%(self.name))r1 = Role('Alex','police',"AK47")r2 = Role('Wupeiqi','terrorist','B22')r1.got_shot()del r1r2.got_shot()# ah.....Alex:I got shot....# Alex 彻底死了# ah.....Wupeiqi:I got shot....# Wupeiqi 彻底死了 |
程序结束、del删除实例时才会执行__del__里的内容
4、私有属性、私有方法
记住私有的概念:只能在类里面进行调用 看完下面的代码你就明白了
|
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
|
#class私有属性、私有方法class Role(object): #定义一个类, class是定义类的语法 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 show_status(self): #定义函数,调用私有属性 print("name:%s weapon:%s life_value:%s"%(self.name,self.weapon,self.__life_value)) def __shot(self): #定义私有方法 print("%s is shooting......."%(self.name)) def got_shot(self): self.__shot() #调用私有方法 print("ah.....%s:I got shot...."%(self.name))r1 = Role('lzl','police',"AK47")#私有属性#print(r1.__life_value) #外部调用life_vaule 直接报错#AttributeError: 'Role' object has no attribute '__life_value'r1.show_status() #通过方法执行私有属性#name:lzl weapon:AK47 life_value:100#私有方法#r1.__shot() #外部调用私有方法 直接报错#AttributeError: 'Role' object has no attribute '__shot'r1.got_shot() #通过其他方法执行私有方法# lzl is shooting.......# ah.....lzl:I got shot.... |
5、继承
继承:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展
|
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
37
38
39
|
#类的继承class People(): 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 play(self): #增加新功能 print("%s is playing...."%self.name) def sleep(self): #重构sleep功能 People.sleep(self) print("man is sleeping....")class Woman(People): #继承类People def get_birth(self): #增加新功能 print("%s is born a boby...."%self.name)m1 = Man("lianzhilie",22)w1 = Woman("Alex",33)m1.eat() #调用People方法m1.play() #调用Man方法# lianzhilie is eating...# lianzhilie is playing....m1.sleep()# lianzhilie is sleeping....# man is sleeping...w1.get_birth()# Alex is born a boby... |
由上面程序可知,类的继承可省大量重复的代码
|
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
|
#类的继承,子类初始化class People(): 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): #重构初始化 覆盖父类 # People.__init__(self,name,age) #加载父类初始化 super(Man,self).__init__(name,age) #加载父类初始化 self.money = money print("%s 一出生就有 $%s"%(self.name,self.money)) def play(self): #增加新功能 print("%s is playing...."%self.name)class Woman(People): def get_birth(self): print("%s is born a boby...."%self.name)m1 = Man("lianzhilie",22,1000)w1 = Woman("Alex",33)#lianzhilie 一出生就有 $1000 |
子类需要重构初始化时,会把父类的初始化覆盖掉,所以在重构时需要加载父类初始化
|
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
|
# 类的继承-多继承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 Relation(object): def make_friends(self,obj): print("%s is making friends with %s"%(self.name,obj.name))class Man(Relation,People): #多继承 def play(self): print("%s is playing...." % self.name)class Woman(People): def get_birth(self): print("%s is born a boby...." % self.name)m1 = Man("lianzhilie", 22)w1 = Woman("Alex", 33)m1.make_friends(w1)#lianzhilie is making friends with Alex |
多继承时需注意,在多继承中从父类继承初始化属性时,顺序从左到右开始初始化,只要初始化到属性数据就不再向后继续,所以越往前越优先;当父类有初始化,子类也有初始化时,执行子类的初始化,父类的不生效
刚才我们已经知道了新式类的概念,那么经典类与新式类的区别是什么呢?!
通过上面的程序我们知道Python的类可以继承多个类,那如果Python的类如果继承了多个类,有多层继承关系,那么其初始化时寻找的路线是什么样的呢?,通过下面这段代码来看下:
|
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
37
|
#经典类class A(): def __init__(self): print("A")class B(A): passclass C(A): def __init__(self): print("C")class D(B,C): passobj = D()#A#新式类class A(object): def __init__(self): print("A")class B(A): passclass C(A): def __init__(self): print("C")class D(B,C): passobj = D()#C |
当类是经典类时,多继承情况下,会按照深度优先方式查找;当类是新式类时,多继承情况下,会按照广度优先方式查找;具体参考下图

6、多态
看完上面的话,完全懵逼; 说人话!!--》一个接口,多种实现,实现接口重用
|
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
|
#多态class Animal: def __init__(self, name): # Constructor of the class self.name = name @staticmethod def animal_talk(obj): obj.talk()class Cat(Animal): def talk(self): print('%s:Meow!'%(self.name))class Dog(Animal): def talk(self): print('%s:Woof! Woof!'%(self.name))c = Cat('Missy')d = Dog('Lassie')Animal.animal_talk(c)Animal.animal_talk(d)# Missy:Meow!# Lassie:Woof! Woof! |
day7 面向对象编程的更多相关文章
- Python之路,Day7 - 面向对象编程进阶
本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 经典类vs新式类 把下面代 ...
- Java学习day7面向对象编程1-对象和类
一.Java编程中对象和类的概念 1,什么是类? 答:类是客观存在的,抽象的,概念的东西. 2,什么是对象? 答:对象是具体的,实际的,代表一个事物.例如:车是一个类,汽车,自行车就是他的对象. 关于 ...
- Day7 - Python基础7 面向对象编程进阶
Python之路,Day7 - 面向对象编程进阶 本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个 ...
- Python之路第一课Day7--随堂笔记(面向对象编程进阶...未完待续 )
本节内容: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 一.静态方法 通过@s ...
- Python基础7 面向对象编程进阶
本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 经典 ...
- Python之路,Day8 - 面向对象编程进阶
本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 经典 ...
- Python之freshman07 面向对象编程jinjie
本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程 经典类vs新式类 把下面代码 ...
- angular2系列教程(六)两种pipe:函数式编程与面向对象编程
今天,我们要讲的是angualr2的pipe这个知识点. 例子
- 带你一分钟理解闭包--js面向对象编程
上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...
随机推荐
- Google maps API开发
原文:Google maps API开发 Google maps API开发(一) 最近做一个小东西用到google map,突击了一下,收获不小,把自己学习的一些小例子记录下来吧 一.加载Googl ...
- MVC验证09-使用MVC的Ajax.BeginForm方法实现异步验证
原文:MVC验证09-使用MVC的Ajax.BeginForm方法实现异步验证 MVC中,关于往后台提交的方法有: 1.Html.BeginForm():同步 2.Ajax.BeginForm():异 ...
- c语言下多线程
原文:c语言下多线程 [问题]创建了10个线程,10个线程公用一个线程体,创建如下: int t1=0,t2=1,t3=2,t4=3,t5=4,t6=5,t7=6,t8=7,t9=8,t10=9; i ...
- ReSharper C++计划上市
ReSharper是著名的VS代码生成工具,去年夏天,JetBrains公司就发布了ReSharper将推出支持C++的版本. ReSharper C++ EAP(Early Access Progr ...
- ubuntu安装nVidia驱动,遇到终端闪砾问题并解决
安装nvidia的官方驱动之后,比起nouvean来说感觉速度快了不少. 安装该驱动很简单,但选择哪个驱动是要注意的.因为今天我试了nvidia的多个驱动后都在ubuntu下用起来并不好. 我现在的环 ...
- Error with mysqld_safe
出处:http://bugs.mysql.com/bug.php?id=18403 Description: - I downloaded the binary file “Standard 5.0. ...
- jquery中的一点工作小记
在做一个页面的时候,网页中由许多块相同的地方 ,例如页面中会有多个地方用到TAB 效果,在使用each()遍历以后 不一定会正常显示,这是因为写的html静态页面中只有当前板块中有这个的类,若是用J ...
- C# 利用SMTP异步发送邮件
C#实现收发邮件功能需要用到两个命名空间 System.Net; 和 System.Net.Mail; SmtpClient client = new SmtpClient("smtp.g ...
- asp.net mvc请求响应模型原理回顾
根据讲师所讲总结了一下(可能存在些描述错误) -------------mvc进入asp.net管道原理: (在执行httpapplication管道之前mvc和asp.net是相同的,不同之处在于管 ...
- Mock原理学习
同事搓蛋问了我一个问题,mock的原理是啥,没怎么想出来,于是花了点时间学习了一下. 从Moq这个库入手:https://github.com/moq/moq4 Moq用到了Castle的库用于Dyn ...