修饰器的概念和作用
什么是修饰器
修饰器又叫装饰器,本身也是一个函数,是在原有的函数或者是方法上增添一些额外的功能。
修饰器的作用
概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
比如说这个函数是注册的功能,但有时候这个用户在执行这个操作的时候,他是已注册的用户,我这个函数已经写好了,不想动它了,那么我们就可以通过修饰器来给这个函数增加一个登录的功能。
它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。从需求谈起
引入
现在,假设我们有一个函数
def foo():
print('in foo()')
foo()
为了检查这个函数的复杂度(在网络编程中程序的延时还是很重要的),需要测算运算时间,增加了计算时间的功能有了下面的代码:
import time
def foo():
start = time.clock()
print('in foo()')
end = time.clock()
print('in foo()')
foo()
这里只是写了一个函数,如果我想测量多个函数的延时,由于必须知道start与end,所以必须写在程序的开头与结尾,难道每一个程序都这样复制粘贴么?固然可行,但是,我们可以通过设计模式中将功能与数据部分分离一样,将这个测量时间的函数分离出去,就像C++中我们可以将这个测量时间的函数变为一个类,通过调用这个类,赋予不同的函数来测量不同的函数的运行时长。在python中,由于函数实际上就是对象,所以可以利用类似的方法实现:
import time
def foo():
print('in foo()')
def timeit(func):
start = time.clock()
func()
end =time.clock()
print('Time Elapsed:', end - start)
timeit(foo)
这里func()就可以指定函数了,但是如果我不想填这个函数或者这个功能函数并不能修改成类似的形式怎么办?我们需要的是最大限度的少改动:
import time
def foo():
print('in foo()')
# 定义一个计时器,传入一个,并返回另一个附加了计时功能的方法
def timeit(func):
# 定义一个内嵌的包装函数,给传入的函数加上计时功能的包装
def wrapper():
start = time.clock()
func()
end =time.clock()
print('Time Elapsed:', end - start)
# 将包装后的函数返回
return wrapper
foo = timeit(foo) #可以直接写成@timeit + foo定义,python的"语法糖"
foo()
在这个代码中,timeit(foo)不是直接产生调用效果,而是返回一个与foo参数列表一致的函数(其实是函数回调),此时此foo非彼foo!因为此时的foo具有了timeit的功效,简单来说就是能够让你在装饰前后执行代码而无须改变函数本身内容,装饰器是一个函数,而其参数为另外一个函数。
修饰器本质
对于Python的这个@注解语法糖- Syntactic Sugar 来说,当你在用某个@decorator来修饰某个函数func时,如下所示:
@decorator
def func():
pass
其解释器会解释成下面这样的语句:
func = decorator(func)
等等…这不就是把一个函数当参数传到另一个函数中,然后再回调吗?是的,但是,我们需要注意,那里还有一个赋值语句,把decorator这个函数的返回值赋值回了原来的func。 根据《函数式编程》中的first class functions中的定义的,你可以把函数当成变量来使用,所以,decorator必需得返回了一个函数出来给func,这就是所谓的higher order function 高阶函数,不然,后面当func()调用的时候就会出错。
注意
-
修饰器的关键字是 @ ,Python代码中只要出现了它,就可以想到是修饰器了
-
修饰器修饰的是函数或者是方法,不能修饰一个类
-
修饰器必须出现在被修饰函数或者方法的前一行,不能够将修饰器定义在函数的同行
个人总结
其实修饰器更像是一个函数,但修饰器将被修饰函数作为形参,先执行修饰器中的语句,再返回传递进来的函数对象(其他函数对象也行),并调用返回出来的函数
reference
谈谈python修饰器 - 简书 (jianshu.com)
本文介绍了Python修饰器的概念和作用,修饰器是一个能在不修改原有函数代码的基础上,为其添加额外功能的函数。常见应用场景包括日志记录、性能测试、事务处理等。修饰器通过高阶函数实现,使用@注解的形式方便地应用到目标函数上,为代码的复用和维护提供了便利。
259

被折叠的 条评论
为什么被折叠?



