python:面向对象
概述
- 面向过程:根据业务逻辑从上到下写垒代码
- 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
- 面向对象:对函数进行分类和封装,让开发“更快更好更强...”
面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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
|
def 发送邮件(内容) #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True : if cpu利用率 > 90 % : 发送邮件( 'CPU报警' ) if 硬盘使用空间 > 90 % : 发送邮件( '硬盘报警' ) if 内存占用 > 80 % : 发送邮件( '内存报警' ) |
创建类和对象
面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。
类就是一个模板,模板里可以包含多个函数,函数里实现一些功能
对象则是根据模板创建的实例,通过实例对象可以执行类中的函数
- class是关键字,表示类
- 创建对象,类名称后加括号即可
ps:类中的函数第一个参数必须是self(详细见:类的三大特性之封装)
类中定义的函数叫做 “方法”
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# 创建类 class Foo: def Bar( self ): print 'Bar' def Hello( self , name): print 'i am %s' % name # 根据类Foo创建对象obj obj = Foo() obj.Bar() #执行Bar方法 obj.Hello( 'wupeiqi' ) #执行Hello方法 |
诶,你在这里是不是有疑问了?使用函数式编程和面向对象编程方式来执行一个“方法”时函数要比面向对象简便
- 面向对象:【创建对象】【通过对象执行方法】
- 函数编程:【执行函数】
观察上述对比答案则是肯定的,然后并非绝对,场景的不同适合其的编程方式也不同。
总结:函数式的应用场景 --> 各个函数之间是独立且无共用的数据
语法
1
2
3
4
5
6
7
8
9
|
class Dog( object ): print ( "hello,I am a dog!" ) d = Dog() #实例化这个类, #此时的d就是类Dog的实例化对象 #实例化,其实就是以Dog类为模版,在内存里开辟一块空间,存上数据,赋值成一个变量名 |
上面的代码其实有问题,想给狗起名字传不进去。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Dog( object ): def __init__( self ,name,dog_type): self .name = name self . type = dog_type def sayhi( self ): print ( "hello,I am a dog, my name is " , self .name) d = Dog( 'LiChuang' , "京巴" ) d.sayhi() |
为什么有__init__? 为什么有self?
画图之前, 你先注释掉这两句
1
2
3
4
|
# d = Dog('LiChuang', "京巴") # d.sayhi() print (Dog) |
没实例直接打印Dog输出如下
1
|
< class '__main__.Dog' > |
这代表什么?代表 即使不实例化,这个Dog类本身也是已经存在内存里的对不对, yes, cool,那实例化时,会产生什么化学反应呢?
静态方法
通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Dog( object ): def __init__( self ,name): self .name = name @staticmethod #把eat方法变为静态方法 def eat( self ): print ( "%s is eating" % self .name) d = Dog( "ChenRonghua" ) d.eat() |
上面的调用会出以下错误,说是eat需要一个self参数,但调用时却没有传递,没错,当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。
1
2
3
4
|
Traceback (most recent call last): File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/静态方法.py" , line 17 , in <module> d.eat() TypeError: eat() missing 1 required positional argument: 'self' |
想让上面的代码可以正常工作有两种办法
1. 调用时主动传递实例本身给eat方法,即d.eat(d)
2. 在eat方法中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其它变量了
1 class Dog(object): 2 3 def __init__(self,name): 4 self.name = name 5 6 @staticmethod 7 def eat(): 8 print(" is eating") 9 10 11 12 d = Dog("ChenRonghua") 13 d.eat()
类方法
类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
1
2
3
4
5
6
7
8
9
10
11
12
|
class Dog( object ): def __init__( self ,name): self .name = name @classmethod def eat( self ): print ( "%s is eating" % self .name) d = Dog( "ChenRonghua" ) d.eat() |
执行报错如下,说Dog没有name属性,因为name是个实例变量,类方法是不能访问实例变量的
1
2
3
4
5
6
|
Traceback (most recent call last): File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/类方法.py" , line 16 , in <module> d.eat() File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/类方法.py" , line 11 , in eat print ( "%s is eating" % self .name) AttributeError: type object 'Dog' has no attribute 'name' |
此时可以定义一个类变量,也叫name,看下执行效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class Dog( object ): name = "我是类变量" def __init__( self ,name): self .name = name @classmethod def eat( self ): print ( "%s is eating" % self .name) d = Dog( "ChenRonghua" ) d.eat() #执行结果 我是类变量 is eating |
属性方法
属性方法的作用就是通过@property把一个方法变成一个静态属性
1
2
3
4
5
6
7
8
9
10
11
12
|
class Dog( object ): def __init__( self ,name): self .name = name @property def eat( self ): print ( " %s is eating" % self .name) d = Dog( "ChenRonghua" ) d.eat() |
调用会出以下错误, 说NoneType is not callable, 因为eat此时已经变成一个静态属性了, 不是方法了, 想调用已经不需要加()号了,直接d.eat就可以了
1
2
3
4
5
|
Traceback (most recent call last): ChenRonghua is eating File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/属性方法.py" , line 16 , in <module> d.eat() TypeError: 'NoneType' object is not callable |
正常调用如下
1
2
3
4
5
|
d = Dog( "ChenRonghua" ) d.eat 输出 ChenRonghua is eating |