python里为什么需要使用装饰器(decorator)
2017-09-24 17:39
555 查看
为什么需要使用装饰器呢?其实很多人学习python之后都会问这个问题。
这一次,我来深入地学习一下什么是装饰器,以及为什么需要它。
其实这个装饰器就是我们这样的程序员太“懒”了,基本上什么事情都想少做,追求是DRY,那么什么是DRY,如下:
DRY(Don't repeat yourself
),字面意思来看:"不要重复自己"。强调的意思就是在进行编程时相同的代码不要重复写,最好只写一次,然后可以在其他地方直接引用。如此一来,可以提高代码重用率,缩减代码量,同时也有助于提高代码的可读性和可维护性。当需要做出更改时,只需要更改一个地方即可。
有了这个指导思想,就很明白了,就是少写代码,装饰器的目的也就是少写代码,复用代码。
复用代码有很多种方式,比如面向对象里的继承,虚函数等,但是想在函数层面来复用代码,有什么方法呢?
一般情况之下,就是函数中调用另一个函数来达到继承和复用。函数里调用别的函数,如下面的例子:
2
1
如果这时,我们想把每个函数添加一行星号打印输出,以便分隔开来,更好看一些,我们往往会这样做修改,
每个函数里添加一行星号就行了,修改如下:
输出如下:
*************************************
2
*************************************
1
当我们只有两个函数时,这样修改很快的,并且很快就完成工作了,但是如果有1000个这样函数呢?那么是否需要添加1000遍?
如果你每个函数去添加一个也是可以完成任务的,但是有想法,或者更聪明的办法,就不是这样了。能否不修改原来的函数,即是原来的函数代码一点都不改变,又能增加这样的功能呢?答案是可以的,如下修改:
*************************************
2
*************************************
1
在这里增加了一个函数,这个函数接收一个函数对象作为参数,这样就不需要修改原来的函数,达到原来稳定并且测试通过的代码不作任何修改,减少出错的风险,特别已经上线运行的系统,更是如此;或者像8代单传的代码,没有人敢去修改它,否则领导会怪你,怎么样把产品越改越差,本来是请你来做好产品的,结果不行。做到这一步,就结束了吗?还不行啊,因为每个调用这个函数的地方都需要修改,因此再继续修改,结果改成这样:
*************************************
2
*************************************
1
这里发现调用add方法,还是不一样,继续修改,代码如下:
*************************************
2
*************************************
1
到这里,可以发现使用嵌套函数来实现,就可以返回一个可调用的对象,这样更加完美了。
def sub():
return 2 -1
sub = printStar(sub)
和
@printStar
def sub():
return 2 -1
由此可见@printStar是一个语法改变,它的目标就是实现不修改原来函数的代码,又可以复用原来的函数并且作出修改,也称作为元编程,并且装饰器函数可以复用,实现共享的目标。
五子棋游戏开发
http://edu.csdn.net/course/detail/5487
这一次,我来深入地学习一下什么是装饰器,以及为什么需要它。
其实这个装饰器就是我们这样的程序员太“懒”了,基本上什么事情都想少做,追求是DRY,那么什么是DRY,如下:
DRY(Don't repeat yourself
),字面意思来看:"不要重复自己"。强调的意思就是在进行编程时相同的代码不要重复写,最好只写一次,然后可以在其他地方直接引用。如此一来,可以提高代码重用率,缩减代码量,同时也有助于提高代码的可读性和可维护性。当需要做出更改时,只需要更改一个地方即可。
有了这个指导思想,就很明白了,就是少写代码,装饰器的目的也就是少写代码,复用代码。
复用代码有很多种方式,比如面向对象里的继承,虚函数等,但是想在函数层面来复用代码,有什么方法呢?
一般情况之下,就是函数中调用另一个函数来达到继承和复用。函数里调用别的函数,如下面的例子:
#python 3.6 def add(): return 1 + 1 def sub(): return 2 -1 print(add()) print(sub())输出如下:
2
1
如果这时,我们想把每个函数添加一行星号打印输出,以便分隔开来,更好看一些,我们往往会这样做修改,
每个函数里添加一行星号就行了,修改如下:
#python 3.6 def add(): print('*************************************') return 1 + 1 def sub(): print('*************************************') return 2 -1 print(add()) print(sub())
输出如下:
*************************************
2
*************************************
1
当我们只有两个函数时,这样修改很快的,并且很快就完成工作了,但是如果有1000个这样函数呢?那么是否需要添加1000遍?
如果你每个函数去添加一个也是可以完成任务的,但是有想法,或者更聪明的办法,就不是这样了。能否不修改原来的函数,即是原来的函数代码一点都不改变,又能增加这样的功能呢?答案是可以的,如下修改:
#python 3.6 def add(): return 1 + 1 def sub(): return 2 -1 #定义一个新的函数 def printStar(func): print('*************************************') return func() print(printStar(add)) print(printStar(sub))输出如下:
*************************************
2
*************************************
1
在这里增加了一个函数,这个函数接收一个函数对象作为参数,这样就不需要修改原来的函数,达到原来稳定并且测试通过的代码不作任何修改,减少出错的风险,特别已经上线运行的系统,更是如此;或者像8代单传的代码,没有人敢去修改它,否则领导会怪你,怎么样把产品越改越差,本来是请你来做好产品的,结果不行。做到这一步,就结束了吗?还不行啊,因为每个调用这个函数的地方都需要修改,因此再继续修改,结果改成这样:
#python 3.6 #定义一个新的函数 def printStar(func): print('*************************************') return func() @printStar def add(): return 1 + 1 def sub(): return 2 -1 print(add) print(printStar(sub))输出结果如下:
*************************************
2
*************************************
1
这里发现调用add方法,还是不一样,继续修改,代码如下:
#python 3.6 #定义一个新的函数 def printStar(func): def f(): print('*************************************') return func() return f @printStar def add(): return 1 + 1 def sub(): return 2 -1 print(add()) sub = printStar(sub) print(sub())输出结果如下:
*************************************
2
*************************************
1
到这里,可以发现使用嵌套函数来实现,就可以返回一个可调用的对象,这样更加完美了。
#python 3.6 #定义一个新的函数 def printStar(func): def f(): print('*************************************') return func() return f @printStar def add(): return 1 + 1 @printStar def sub(): return 2 -1 print(add()) print(sub())在这里可以发现这两段代码是相等的:
def sub():
return 2 -1
sub = printStar(sub)
和
@printStar
def sub():
return 2 -1
由此可见@printStar是一个语法改变,它的目标就是实现不修改原来函数的代码,又可以复用原来的函数并且作出修改,也称作为元编程,并且装饰器函数可以复用,实现共享的目标。
Python游戏开发入门
http://edu.csdn.net/course/detail/5690你也能动手修改C编译器
http://edu.csdn.net/course/detail/5582纸牌游戏开发
http://edu.csdn.net/course/detail/5538
五子棋游戏开发
http://edu.csdn.net/course/detail/5487
RPG游戏从入门到精通
http://edu.csdn.net/course/detail/5246
WiX安装工具的使用
http://edu.csdn.net/course/detail/5207
俄罗斯方块游戏开发
http://edu.csdn.net/course/detail/5110
boost库入门基础
http://edu.csdn.net/course/detail/5029
Arduino入门基础
http://edu.csdn.net/course/detail/4931
Unity5.x游戏基础入门
http://edu.csdn.net/course/detail/4810
TensorFlow API攻略
http://edu.csdn.net/course/detail/4495
TensorFlow入门基本教程
http://edu.csdn.net/course/detail/4369
C++标准模板库从入门到精通
http://edu.csdn.net/course/detail/3324
跟老菜鸟学C++
http://edu.csdn.net/course/detail/2901
跟老菜鸟学python
http://edu.csdn.net/course/detail/2592
在VC2015里学会使用tinyxml库
http://edu.csdn.net/course/detail/2590
在Windows下SVN的版本管理与实战
http://edu.csdn.net/course/detail/2579
Visual Studio 2015开发C++程序的基本使用
http://edu.csdn.net/course/detail/2570
在VC2015里使用protobuf协议
http://edu.csdn.net/course/detail/2582
在VC2015里学会使用MySQL数据库
http://edu.csdn.net/course/detail/2672
相关文章推荐
- Python如何使用装饰器(Decorator)修改yield function返回值
- Python 为什么需要使用__name__=='__main__'
- Python中使用装饰器时需要注意的一些问题
- Python学习笔记--为什么需要使用__name__=='__main__'
- Python中使用装饰器时需要注意的一些问题
- Python中的Decorator(装饰器)模式
- Python:decorator的使用
- C++使用boost python开发后发布程序需要注意的几点
- 呼叫中心为什么需要使用桌面虚拟化方案?
- 为什么需要使用MQ?
- Python中decorator的使用
- python判断变量类型时,为什么不推荐使用type()方法
- Java Generic(-) 为什么需要使用泛型
- 为什么内部类访问的外部变量需要使用final修饰
- Delphi、Python使用CGI Apache的配置文件需要修改的事项
- 为什么使用Python
- Python: 使用装饰器“@”取得函数执行时间
- Python的walk和Decorator使用一例
- 为什么Android系统需要使用C、C++和Java语言共同开发
- jdk1.5为什么需要使用@Override标记,其作用是什么