装饰器(Decorator)
在Python程序中,装饰器就是一种闭包,它可以使闭包的访问方式更简单。
例如有定义 fun1 和 fun2 函数,代码如下:
def fun1():
print('功能1')
def fun2():
print('功能2')
现在,假设我们要增强 fun1() 函数和 fun2() 函数的功能,比如,在函数调用之前自动打印日志,又不希望修改函数的代码,这种在代码运行期间动态增加功能的方式,称之为“装饰器”。
本质上,decorator 就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的 decorator,可以定义如下:
import time
def writeLog(func):
try:
f = open("log.txt", 'a', 'utf-8')
f.write(func.__name__)
f.write('\t')
f.write(time.asctime())
f.write('\n')
except Exception as e:
print(e.args)
finally:
f.close()
#不修改源代码的基础上,添加日志功能
def funcOut(func):
def funcIn():
writeLog(func)
func()
return funcIn
在Python中使用装饰器,需要使用特殊符号“@”来实现。在定义装饰器函数或类时,使用“@装饰器名称”的形式将符号“@”放在函数或类的定义行之前。
@funcOut
def fun1():
print('功能1')
@funcOut
def fun2():
print('功能2')
在使用装饰器后,再调用函数 fun1 和 fun2 与普通函数调用没有区别,而装饰器定义的功能会自动插入函数 fun1 和 fun2 中。
fun1()
fun2()
装饰器使用示例源代码
#使用装饰器 完成不修改fun1() fun2()函数的源码,添加输出日志信息
import time
def writeLog(func):
try:
file = open('log.txt', 'a', encoding='utf-8')
file.write('访问:')
file.write(func.__name__)
file.write('\t')
file.write('时间:')
file.write(time.asctime())
file.write('\n')
except Exception as e:
print(e.args)
finally:
file.close()
#使用闭包
def funcOut(func):
def funcIn():
writeLog(func)
func()
return funcIn
@funcOut
def fun1():
print('功能1')
@funcOut
def fun2():
print('功能2')
#闭包的调用
fun1()
fun2()
【示例】使用装饰器给 foo() 函数增加功能
#给 foo 函数运行之前加输入print('I am foo')语句
def funcOut(func):
def funcIn():
print('I am foo')
func()
return funcIn
@funcOut
def foo():
print('foo 函数正在运行')
foo()
执行结果
【示例】多个装饰器
def funcOut(func):
print('我是装饰器1')
def funcIn():
print('I am foo')
func()
return funIn
def funOut2(func):
print('我是装饰器2')
def funcIn():
print('hello')
func()
return funIn
@funcOut
@funcOut2
def foo():
print('foo 函数正在运行')
foo()
执行结果:
由上面的示例可以看出,若给功能函数添加多个装饰器时,离功能函数最近的先进行装饰。
【示例】指定参数的装饰器
#两个参数
def funcOut(func):
def funcIn(x, y):
func(x, y)
return funcIn
@funcOut
def test(a, b):
print('参数a b的值:', a, b)
test(10, 20)
#三个参数
def funcOut1(func):
def funcIn(x, y, z):
func(x, y, z)
return funcIn
@funcOut1
def test1(a, b, c):
print('参数a b c的值:', a, b, c)
test1(10, 20, 30)
执行结果
【示例】通用的装饰器
def funcOut(func):
def funcIn(*args, **kwargs):
return func(*args, **kwargs)
return funcIn
@funcOut
def test1(a):
print('一个参数a:', a)
@funcOut
def test2(a, b):
print('两个参数a、b:', a, b)
@funcOut
def test3(a, b, c):
print('三个参数a、b、c:', a, b, c)
test1(10)
test2(10, 20)
test3(10, 20, 30)
执行结果: