1 - 简介
当我们执行某一些函数的时候, 可能会在其之前或者之后执行一些操作, 下面是一个常见的例子:
import time
def test ():
n = 0
for i in range (10000):
n += i
return n
t = time.time ()
test ()
spend = time.time() - t
print ("it took ", spend, "s")
上面这个例子实现了一个计时器, 用来统计函数执行的时间, 但是如果你需要在你的程序中大量复用这一个计时器的时候, 就会显得很复杂而且不可维护, 于是装饰器应运而生, 用来解决这一问题
说了这么多, 其实装饰器的作用就是帮助你在执行某些函数之前或者之后执行一些操作.
2 - 前置知识
2 - 1 闭包
关于闭包的详细知识: https://zhuanlan.zhihu.com/p/21680710
如果你不了解闭包也没有太大的问题, 你只需要知道一件事情:
当一个函数(f) 返回了其子函数对象(g) 的时候, 那么这个函数(f)的内置变量会被保存.
例子:
def foo():
x = 5
def inner():
nonlocal x
x += 1
return x
return inner
p = foo()
在上面的例子中, inner 被其父函数 foo 返回, 所以 foo 中的变量会被保存, 以至于 inner 可以访问到 foo 中的变量
2 - 2 变长参数
详细知识请查看: https://www.runoob.com/python3/python3-function.html
例子:
def a (**kwargs):
print (kwargs)
args = {
"abc": 1,
"def": 2
}
a (name="dog", **args)
>>> {'name': 'dog', 'abc': 1, 'def': 2}
我们定义了一个函数 a , 但是 a 可能会有很多个参数, 所以使用 两个星号(**) 定义一个用来存放参数的字典kwargs, 无法被固定参数接受的其他参数就会被存放到 kwargs 中
3 - 手动实现一个装饰器
# 计算运行时间的装饰器例子
import time
def decorater (func):
def wapper ():
t = time.time ()
func ()
print ("it took about ", time.time ()-t , "s")
return wapper
def test ():
n = 0
for i in range (1000000):
n += i
return n
# 此方法实现了函数可复用.
test = decorater (test)
本例子的核心在于 test = decorater (test)
这一句, 这一句代码把原来的 test
函数指向 decorater
返回的 wapper
函数, 在此之后当你调用 test
, 实际上你调用的是 wapper