Py西游攻关之面向对象(一)
面向对象概述
抛个需求给大家,写一个程序,对你的电脑无论是cpu的使用率,内存还是硬盘超过一定值后给你的邮箱发一个警告邮件;
是不是很简单,按照我们面向过程的思想很容易就实现了:
while True: if cpu利用率 > 90%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 硬盘使用空间 > 90%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 内存占用 > 80%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接
但,这种写法犯了编程的大忌:代码重复。而当我们学习了函数后,就可以利用函数化编程的思想对其进行改善:
def 发送邮件(内容) #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90%: 发送邮件('CPU报警') if 硬盘使用空间 > 90%: 发送邮件('硬盘报警') if 内存占用 > 80%: 发送邮件('内存报警')
而今天我们就来学习另外一种,也是最重要的一种解决问题的编程思想:面向对象编程
首先,我们来看下它的定义:
面向对象程序设计(英语:Object-oriented programming,缩写:OOP)是一种程序设计范型,同时也是一种程序开发的方法。对象指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。
面向对象程序设计可以看作一种在程序中包含各种独立而又互相调用的对象的思想,这与传统的思想刚好相反:传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对电脑下达的指令。面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个小型的“机器”,即对象。
不明白?没关系,我们来举一个例子:请问,大象进冰箱拢共分几步?
1 打开冰箱
2 大象走进去
3 关上冰箱
是的,这就是面向过程的思想,那如果用面向对象怎么来实现呢?
首先我们需要分析在这个场景中涉及的几个对象:冰箱和大象,而它们都是具体的存在(对象),是看得见,摸的着的,冰箱长两米,宽一米,海尔牌的;大象是灰色的,重一吨;为了拿到这两个对象,我们需要去创建它们的类
所以 第一步: 创建大象类和冰箱类
第二步: 用对应类实例出场景中的对象,每个类都有属于自己的方法,比如冰箱,可以为它绑定两个方法:打开和关闭大象可以绑定一个进入冰箱的方法,而每一个实例对象都可以去调用类绑定的方法
第三部: 冰箱实例对象.打开()
大象例对象.进冰箱()
冰箱实例对象.关闭()
相同的功能实现,只不过是从对象的角度去分析问题了,而这种方式则是。。。。
类与对象
面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。
简言之:对象=属性+行为(方法)
把具有相同属性和方法的对象归为一类。类是对象的抽象化,对象是类的实例化。
类就是一个模板,模板里可以包含多个函数,函数里实现一些功能,对象则是根据模板创建的实例,通过实例对象可以执行类中的函数。
这里我们创建了大象类elephant,定义了一个实例方法go_in_fridge(),用于供对象调用,而e1就是我们创建的大象的实例对象。
这里必须强调self这个参数。
self指的是类实例对象本身(注意:不是类本身),在定义类的实例方法时必须写在第一个参数位置上,但在调用该实例方法时不必传入。在我们的例子中,当我们创建了e1后,self即代指e1这个实例对象了。
下面我们再来创建冰箱类:
__init__()方法是在实例对象时,即fridge("海尔","白色")时自动执行的方法,叫构造方法;self.color,self.brand都是实例对象的属性。
诶,你在这里是不是有疑问了?使用函数式编程和面向对象编程方式来执行一个“方法”时函数要比面向对象简便
- 面向对象:【创建对象】【通过对象执行方法】
- 函数编程:【执行函数】
观察上述对比答案则是肯定的,然后并非绝对,场景的不同适合其的编程方式也不同。
总结:函数式的应用场景 --> 各个函数之间是独立且无共用的数据
问答专区
1 什么样的代码才是面向对象?
答:从简单来说,如果程序中的所有功能都是用 类 和 对象 来实现,那么就是面向对象编程了。
2 函数式编程 和 面向对象 如何选择?分别在什么情况下使用?
答:须知:对于 C# 和 Java 程序员来说不存在这个问题,因为该两门语言只支持面向对象编程(不支持函数式编程)。而对于 Python 和 PHP 等语言却同时 支持两种编程方式,且函数式编程能完成的操作,面向对象都可以实现;而面向对象的能完成的操作,函数式编程不行(函数式编程无法实现面向对象的封装 功能)。所以,一般在Python开发中,全部使用面向对象 或 面向对象和函数式混合使用面向对象的应用场景:
<1>多函数需使用共同的值,如:数据库的增、删、改、查操作都需要连接数据库字符串、主机名、用户名和密码
class SqlHelper: def __init__(self, host, user, pwd): self.host = host self.user = user self.pwd = pwd def 增(self): # 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接 # do something # 关闭数据库连接 def 删(self): # 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接 # do something # 关闭数据库连接 def 改(self): # 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接 # do something # 关闭数据库连接 def 查(self): # 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接 # do something # 关闭数据库连接# do something
<2>需要创建多个事物,每个事物属性个数相同,但是值的需求
如:张三、李四、杨五,他们都有姓名、年龄、血型,但其都是不相同。即:属性个数相同,但值不相同
class Person: def __init__(self, name ,age ,blood_type): self.name = name self.age = age self.blood_type = blood_type def detail(self): temp = "i am %s, age %s , blood type %s " % (self.name, self.age, self.blood_type) print temp zhangsan = Person('张三', 18, 'A') lisi = Person('李四', 73, 'AB') yangwu = Person('杨五', 84, 'A')
3 类和对象在内存中是如何保存?
类以及类中的方法在内存中只有一份,而根据类创建的每一个对象都在内存中需要存一份,大致如下图:
如上图所示,根据类创建对象时,对象中除了封装 brand 和 color 的值之外,还会保存一个类对象指针,该值指向当前对象的类。
当通过 obj1 执行 open() 时,过程如下:
- 根据当前对象中的 类对象指针 找到类中的方法
- 将对象 obj1 当作参数传给 方法的第一个参数 self