python之装饰器
想理解python装饰器,首先需要了解高阶函数和内嵌函数,这些在上一篇函数中有介绍,这里就不赘述了。
装饰器的作用就是装饰一个函数,给这个函数增加某些功能。
为什么要使用装饰器呢?因为一个函数已经实现了某些具体的功能,而我们想要增加某些功能,但是又不希望修改源代码,避免增加不必要的问题,而且也不修改其调用方式(可能存在很多调用,不想全部找到并修改)。
下面我们逐步来讲解:
回调函数
import time
def deco(func):
star_time = time.time()
ret = func()
end_time = time.time()
print("running time is %s" % (end_time - star_time))
return ret # 加上返回值,若原函数func的返回值有用,我们也需要将其返回
def test1():
time.sleep(2)
print("in the test1")
#test1() # 原调用方式
deco(test1) # 新调用方式
很明显上面那段代码我们修改了函数的调用方式。
在看下面:
import time
def timer(func):
def deco():
star_time = time.time()
ret = func()
end_time = time.time()
print("running time is %s" % (end_time - star_time))
return ret # 加上返回值,若原函数func的返回值有用,我们也需要将其返回
return deco
def test1():
time.sleep(2)
print("in the test1")
test1 = timer(test1)
test1()
上面的代码基本上就实现了装饰器的功能了,我们没有修改原函数,也没有修改函数的调用方式,只是在该函数的定义后加上了funcname = decorator(funcname)
下面我们来看下真正的装饰器是怎么样的:
def timer(func):
def deco():
star_time = time.time()
ret = func()
end_time = time.time()
print("running time is %s" % (end_time - star_time))
return ret # 加上返回值,若原函数func的返回值有用,我们也需要将其返回
return deco
@timer #实际上就是 test1 = timer(test1),不同点在于,在函数定义前。
def test1():
time.sleep(2)
print("in the test1")
print(test1.__name__) # 看一下我们调用的函数名
test1()
deco
in the test1
running time is 2.0000593662261963
对比上面代码和第二段代码,我们可以发现,实际上的区别就只有一句话而已,@是python内部提供的方法,当然,必须放在修饰的函数前。
而函数名也恰恰证明了我们的猜想,修饰后,test1调用的函数确实是deco函数。
如果我们修饰的函数有参数该怎么处理呢(一个装饰器可能修饰多个不同的函数,参数个数也不一致)?请看下面的代码:
def log(func):
def deco(*args,**kwargs):
print("log:",func.__name__)
return func(*args,**kwargs)
return deco
@log
def test(str):
print("in the test: ",str)
test("hello")
上面我们之前学的可变参数就排上用场了,这样装饰器就可以装饰形参数不同的函数了。
如果说我们的装饰函数需要接收参数呢?那么我们就需要三级嵌套了:
def log(str):
def deco(func):
def note(*args):
print("%s : %s" % (str,"this is decorator!"))
return func()
return note
return deco
@log("sylvain") #相当于 test1 = log("sylvain")(test1)
def test1():
print("in the test1")
print(test1.__name__)
test1()
好了,关于装饰器就知道这么多了,有错误欢迎指正!