Python面向对象开篇

Python是一门非常适合初学者学习的语言。Python本身是支持面向对象编程的。但是在运维界,Python很多时候被称之为脚本语言,因为Python不仅仅支持面向对象编程,还支持函数式编程。这是Java和C#这种OOP语言所不支持的

Linux中的bash shell被当做一种脚本语言,本身也是支持函数式编程的,但是很多时候,shell的面向过程编程简单、粗暴、高效

而Python不仅仅支持OOP面向对象编程,还支持脚本语言的特性,相面过程编程和函数式编程

概述

  • 面向过程:根据业务逻辑从上到下写代码
  • 函数式编程:将某个功能的代码封装到一个函数中,后面用到该功能的时候无需重新编写,仅需要调用函数即可
  • 面向过程:对函数进行分类和封装,终极目标“消除重复代码”

我的OOP启蒙导师之一 Mars(之前是千峰教育的负责人,2016年离职创业,现在是育知同创的创始人之一)曾经给OOP一个比喻,说重复代码就好比是别人往你的脸上吐了口痰,我们的终极目标就是“消除重复代码”

首先来感受下面向过程编程和函数式编程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 面向过程编程
while True
if cpu利用率 > 90%:
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接

if 硬盘使用空间 > 90%:
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接

if 内存占用 > 80%:
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 函数式编程
def 发送邮件(内容)
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接

while True

if cpu利用率 > 90%:
发送邮件('CPU报警')

if 硬盘使用空间 > 90%:
发送邮件('硬盘报警')

if 内存占用 > 80%:
发送邮件('内存报警')

每种写法都有自己存在的价值,世界上没有最好的编程方式,只有最合适的编程方式

创建类和对象

1
2
3
4
5
6
7
8
9
10
11
12
# 创建类
class Foo:

# 创建类中的函数(类中的函数又被称作类的方法)
def func(self):

# 函数体 方法体
pass

# 创建Foo这个类的对象
# 创建一个类的对象,又被称作类的实例化对象
obj = Foo()

体验一下上面的报警功能用OOP是如何实现的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class mail():
def 发送邮件(self, 内容):
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接

m = mail()
while True
if cpu利用率 > 90%:
m.发送邮件('CPU报警')

if 硬盘使用空间 > 90%:
m.发送邮件('硬盘报警')

if 内存占用 > 80%:
m.发送邮件('内存报警')

为什么用了OOP,反而代码量比函数式编程还要多了呢,而且调用方法时不能直接调用了,需要使用mail类的对象来调用。

总结:OOP的优势在极少的代码量的情况下很难体现出来。而且应对不同场景,使用不通的方式编程很重要。函数式编程的应用场景–>各个函数之间是独立的且没有共用的数据。

类和对象的创建

1
2
3
4
5
6
7
8
9
# 创建类
class Foo:

# 创建类中的函数
def func(self):
pass

# 根据类Foo创建对象obj
obj = Foo()

对象和类的关系

创建类

1
2
3
class Foo:
def func(self):
pass

创建对象

1
2
3
4
5
obj1 = Foo()
obj2 = Foo()

obj1.func()
obj2.func()

上面的代码中,我们使用Foo类分别创建了obj1obj2两个对象,在调用Foo类中的func方法时(调用对象方法),Python帮我们隐式地将这个对象传递给了func函数的self参数。在一个类的众多对象中,就是通过隐式的把自己传递给self参数,从而实现了每个对象个性之处。

每一个由类实例化出来的对象,都保存了一个类对象指针指向自己的类

形式参数self

在创建类的时候,如果我们需要让一个方法在不同的对象操作时实现不同的效果,那么我们就需要把这个方法创建成为对象方法。类中的对象方法有个很明显的标记就是self关键字,每个对象方法的头一个参数,都是self!

这个self起到的作用就是区分不同的对象,从而实现对象不同,方法执行的效果就不同。我们在实例化一个对象的时候,该对象调用类中的对象方法,不需要显示的去给self参数传值,因为Python会隐式的帮我们把对象的名字传递给对象方法中的第一个self参数。简单的说,就是哪个对象去执行对象方法,self就是谁。例如上面的例子中,obj1obj2分别调用了对象方法,那么obj1调用func时,self就等于obj1obj2调用func时,self就等于obj2

构造方法/构造函数

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
# 操作MySQL数据库的类
class ConnMySQL:
# 构造方法 __init__(self)
def __init__(self, host, port, username, pasword):
print(self, '每一个对象被创建的时候都会执行这个方法')
self.host = host
self.port = port
self.username = username
self.password = possword

def select(self, sql):
pass

def add(self, sql):
pass

def delete(self, sql):
pass

def modify(self, sql):
pass

# 实例化操作MySQL数据库的对象
my1 = ConnMySQL('192.168.1.1', 3306, 'root', 'p@55\/\/0rd')
my2 = ConnMySQL('192.168.1.2', 3307, 'admin', 'password')

# 使用对象去操作数据库
# 分别去两个数据库中操作sql语句
my1.select('select uid, username, password from userinfo where age=26')
my2.select('select uid, username, password from userinfo where age=26')

注意

  • 在函数式编程中,Python解释器从上向下解释执行,如果一个方法A中依赖另一个方法B,那么B必须要在A之前定义,否则Python解释器会报错。但是在类中不需要,类中的函数可以调用任意位置的函数。