python 装饰器的使用总结

python装饰器:扩展原来函数功能的一种函数(它返回的是一个函数)。

作用:在不修改原代码的基础上给原函数增加新的功能,一般而言我们原始的函数需要增加一些功能,最直接的方法就是去原代码函数中进行修改,那么如果许多个函数都需要增加某个功能呢?这样就特别浪费时间,so,python的装饰器就这么厉害,接下来我们通过例子来了解python的装饰器。

原始函数(举比较简单的例子):

def func_test1():
print( "This is a function named function_test1")

def func_test2():
print( "This is a function named function_test2")


突然有一天我们需要在在所有函数增加统计函数的执行时间功能,此时可以写一个装饰器(可以看到该装饰器接收的是一个函数名,返回的也是一个函数):

def decorator( func):
def wrapper():
startime = time.time()
func()
endtime = time.time()
print(func. __name__ + " spend time " + str(endtime-startime))
return wrapper

那么问题来了,增加这个装饰器函数就可以了吗?当然不是,我们需要使用“@”符号来引用它,在所有需要修改的函数之前添加“@装饰器函数名”。

@decorator
def func_test1():
print( "This is a function named function_test1")

@decorator
def func_test2():
print( "This is a function named function_test2")

func_test1()
func_test2()


执行结果:

PS D:\ python\class\decorator> python .\r2.py
This is a function named function_test1
func_test1 spend time 0.00029206275939941406
This is a function named function_test2
func_test2 spend time 0.0
PS D:\ python\class\decorator>


上面的装饰器或许对于初学的你还有些不是很清楚,接下来举个带参数的装饰器或许你会恍然大悟(通过参数对应的输出来理解装饰器):

def decorator( func):
def wrapper(* args):
startime = time.time()
func(*args)
endtime = time.time()
print(func. __name__ + " spend time " + str(endtime-startime))
return wrapper

@decorator
def func_test1( func_arg1):
print( "This is a function named " + func_arg1)

@decorator
def func_test2( func_arg1, func_arg2):
print( "This is a function named " + func_arg1)
print( "This is a function named " + func_arg2)

func_test1( 'function1')
func_test2( 'function1', 'function2')


运行结果:

PS D:\ python\class\decorator> python .\r2.py
This is a function named function1
func_test1 spend time 0.0
This is a function named function1
This is a function named function2
func_test2 spend time 0.0004956722259521484
PS D:\ python\class\decorator>

注意:装饰器嵌套函数使用的是可变参数,为了方式原始函数带有不同个数的参数。

问题:如果存在关键字参数,装饰器如果写呢?同理我们只需要在装饰函数中添加关键字形参(在实际应用中比较少用)。

def decorator( func):
def wrapper(* args,** kw):
startime = time.time()
func(*args,**kw)
endtime = time.time()
print(func. __name__ + " spend time " + str(endtime-startime))
return wrapper

@decorator
def func_test1( func_arg1):
print( "This is a function named " + func_arg1)

@decorator
def func_test2( func_arg1, func_arg2):
print( "This is a function named " + func_arg1)
print( "This is a function named " + func_arg2)

@decorator
def func_test3( func_arg1, func_arg2,** kw):
print( "This is a function named " + func_arg1)
print( "This is a function named " + func_arg2)
print( "keyword params " + str(kw))

func_test1( 'function1')
func_test2( 'function1', 'function2')
func_test3( 'function1', 'function2', a= 1, b= False, c= '123')

运行结果:

PS D:\ python\class\decorator> python .\r2.py
This is a function named function1
func_test1 spend time 0.0004956722259521484
This is a function named function1
This is a function named function2
func_test2 spend time 0.0004944801330566406
This is a function named function1
This is a function named function2
keyword params { 'a': 1, 'b': False, 'c': '123'}
func_test3 spend time 0.0004980564117431641
PS D:\ python\class\decorator>


我们会发现:加上装饰器func_test1.__name__的值是wrapper,帮助信息也变成了wrapper的信息,是因为我们的函数名称传递给装饰器后实质上执行的是wrapper函数,这样就会造成影响了我们的原始代码的结果。

def decorator( func):
def wrapper():
startime = time.time()
func()
endtime = time.time()
print(func. __name__ + " spend time " + str(endtime-startime))
return wrapper

@decorator
def func_test1():
'''
This function is a test
'''
print( "This is a function named " + func_test1. __name__)

func_test1()
help(func_test1)


PS D:\ python\class\decorator> python .\r3.py
This is a function named wrapper
func_test1 spend time 0.0005042552947998047
Help on function wrapper in module __main__:

wrapper()

PS D:\ python\class\decorator>

对于这个影响我们可以通过引入装饰wraps来避免这个问题,我们需要从functiontools这个模块库加载wraps:

import time
from functools import wraps

def decorator( func):
@wraps(func)
def wrapper():
startime = time.time()
func()
endtime = time.time()
print(func. __name__ + " spend time " + str(endtime-startime))
return wrapper

@decorator
def func_test1():
'''
This function is a test
'''
print( "This is a function named " + func_test1. __name__)

func_test1()
help(func_test1)

PS D:\ python\class\decorator> python .\r3.py
This is a function named func_test1
func_test1 spend time 0.0
Help on function func_test1 in module __main__:

func_test1()
This function is a test

PS D:\ python\class\decorator>

可以看出原始函数的帮助信息和名称不变,是因为wraps装饰器参数func接收的是原始函数,它会把原有函数的一系列信息复制到wrapper函数中。





猜你喜欢

转载自blog.csdn.net/mpu_nice/article/details/80910479