由于没有真正实用经验,所以只记录基本用法,以免经常不用忘的太彻底。
简单说,decorator也是一个函数,可以在不更改另一个函数的情况下,改变或增加另一个函数的功能。
1,不使用装饰器。
def decoTest(func):
print("before")
func()
print("after")
def test():
print('Hello, World')
decoTest(test)
为了达到在test()执行前后分别执行不同语句功能,将test作为参数,传入decoTest中。之后需要调用decoTest函数,如果想直接调用test来达到这个目的,需要使用装饰器。
2,使用@语法
def decoTest(func):
print("before")
func()
print("after")
return func
@decoTest
def test():
print('Hello, World')
test
在decoTest中增加了返回值,返回传入的函数。相当于执行了decoTest(test)。所以结果与上面的相同。所以如果最后调用的是test(),将多输出一个Hello, World。
3,为解决2中调用test()多输出一个Hello, World。对decoTest进行包装,使它返回一个函数。
def decoTest(func):
def wrapper():
print('before')
func()
print('after')
return wrapper
@decoTest
def test():
print('Hello, World')
test()
此时的输出不会再多一行。因为返回的是函数,执行test()相当是将test传入decoTest中,decoTest返回wrapper,此时因为执行的是test(),所以最终会执行wrapper()。
4,解决带参数函数的装饰。
def decoTest(func):
def wrapper(a, b):
print('before')
func(a, b)
print('after')
return wrapper
@decoTest
def test(a, b):
print('a + b =', a + b)
test(2, 9)
结果为:
before a + b = 11 after
因为装饰器函数返回的是一个函数,所以可以接受参数。所以2,9也传入了wrapper中,所以返回正确。
5,使用*, **来解决参数数量的不确定性。
def decoTest(func):
def wrapper(*args, **kwargs):
print('before')
func(*args, **kwargs)
print('after')
return wrapper
@decoTest
def test(a, b, c, d):
print('sum =', a + b + c + d)
@decoTest
def test2(*args, **kwargs):
print("%s, %s" % (args, kwargs))
test(2, 9, 10, 23)
test2(2, 3, 5, a = 5, c = 2)
test和test2都实现了在本身函数之前之后分别输出某个语句。
6,装饰器函数也可以传入参数。
def deco(arg) :
def decoTest(func):
def wrapper(*args, **kwargs):
print('before', arg)
func(*args, **kwargs)
print('after', arg)
return wrapper
return decoTest
@deco("test")
def test(a, b, c, d):
print('sum =', a + b + c + d)
@deco("test2")
def test2(*args, **kwargs):
print("%s, %s" % (args, kwargs))
test(2, 9, 10, 23)
test2(2, 3, 5, a = 5, c = 2)
输出结果为:
before test
sum = 44
after test
before test2
(2, 3, 5), {'c': 2, 'a': 5}
after test2
装饰器函数里面嵌套定义了两个函数。例子中装饰器函数为deco,deco返回的是函数decoTest,decoTest有一个函数参数,装饰器返回的函数可以接受另一个函数,而decoTest又返回了wrapper函数。所以decoTest函数可以接受多个参数并最终输出。