python里为什么需要使用装饰器(decorator)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/caimouse/article/details/78078189
为什么需要使用装饰器呢?其实很多人学习python之后都会问这个问题。
这一次,我来深入地学习一下什么是装饰器,以及为什么需要它。
其实这个装饰器就是我们这样的程序员太“懒”了,基本上什么事情都想少做,追求是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游戏开发入门

你也能动手修改C编译器

纸牌游戏开发

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


阅读更多

扫码向博主提问

caimouse

博客专家

非学,无以致疑;非问,无以广识
去开通我的Chat快问

没有更多推荐了,返回首页