装饰器
1.
用于拓展原来函数功能的一种函数
2.
返回函数的函数
3.
在不用更改原函数的代码前提下给函数增加新的功能
//如果没有装饰器
def hello():
print('hello world')
def test():
print('test...')
def hello_wrapper():
//新的函数,包裹原来的hello
print('进入函数hello')
hello()
print('结束执行hello')
def test_wrapper():
print('进入函数hello')
test()
print('结束执行hello')
if __name__ == '__main__':
//要实现这样的功能,就要建立多个wrapper(),而且有变化需要修改多个地方,不好维护
hello_wrapper()
test_wrapper()
//实现装饰器,用装饰器实现
def log(func)
//记录函数执行的日志
def wrapper():
print('start...')
func()
print('end...')
def log_in(func)
//记录函数执行的日志
def wrapper():
print('开始...')
func()
print('结束...')
@log
def hello():
//简单功能模拟
print('hello world')
@log
@log_in //装饰器可以使用多个,按顺序嵌套执行
def test()
print('test...')
if __name__ == '__main__':
hello()
test()
//带参数的装饰器
def log(name = None): //允许默认值,可以不传参
def decorator(fun):
def wrapper():
print('{0} start...'.format(name))
fun()
print('{0} end...'.format(name))
return wrapper
return decorator //返回函数不要带括号
@log('hello') //也可以不传参 @log()
def hello():
print('hello world')
@log('test')
def test():
print('test...')
if __name__ == '__main__':
hello()
test()
//如果带参数的装饰器,同时自定义的函数本身也带参数和返回值,如何传递使用
def log(name = None): //允许默认值,可以不传参
def decorator(func):
def wrapper(*args, **kwargs): //这里就要传入add(a, b)的参数.用两个魔法参数,一个元组,一个字典
print('{0} start...'.format(name))
rest = func(*args, **kwargs) //这里就要传入add(a, b)的参数,用一个临时变量保存返回值
print('{0} end...'.format(name))
return rest //为了执行上一句打印,在这里返回临时变量值
return wrapper
return decorator //返回函数不要带括号
@log('hello') //也可以不传参 @log()
def hello():
print('hello world')
@log('test')
def test():
print('test...')
def add(a, b, *args, **kwargs): //有参数,有返回值,如何使用,带两个魔法参数,传更多的变量
return a + b
if __name__ == '__main__':
//hello()
//test()
rest = add(5, 6, k = 5, v = 6)
///装饰器之wraps
def log(name = None): //允许默认值,可以不传参
def decorator(func):
@wraps(func) //j加上这个装饰器,就可以解决注释__doc__和名字__name__等被改变的问题
def wrapper(*args, **kwargs): //这里就要传入add(a, b)的参数.用两个魔法参数,一个元组,一个字典
//注释:装饰器内部的函数
print('{0} start...'.format(name))
rest = func(*args, **kwargs) //这里就要传入add(a, b)的参数,用一个临时变量保存返回值
print('{0} end...'.format(name))
return rest //为了执行上一句打印,在这里返回临时变量值
//原始hello()的注释名字是在这附近发生了改变 ,如果不用@wraps需要在下面进行手动更改
//wrapper.__doc__ = func.__doc__
//wrapper.__name__ = func.__name__
//但是每个都这么操纵很麻烦,所以pyton提供了一个@wraps用来使用,放在装饰器内部函数上
return wrapper
return decorator //返回函数不要带括号
@log('hello') //也可以不传参 @log()
def hello():
//注释:简单功能模拟
print('hello world')
if __name__ == '__main__':
print('doc: {0}'.format(hello.__doc__))
print('doc: {0}'.format(hello.__name__)) //结果注释和名字都不是hello()的,而是变成了装饰器内部的函数wrapper()的注释和名字,这时候就需要用到@wraps
hello()
///装饰器注意事项:
1,用@wraps 还原原始函数的注释\名字等信息
2,用魔法传参 *args, **kwargs 解决自己的函数传参问题
3,自己的函数有返回值的,把函数返回值用临时变量保存起来,执行完装饰器内逻辑后,再return
4,也可以用于类
///类的装饰器
def f(self): //可以在这里扩展类的方法
print('{0}: 我爱吃东西'.format(self.name))
print('000000') //
def eat(cls):
//cls.eat = lambda self: print('{0}: 我爱吃东西'.format(self.name)) //简单的用lambda,更丰富可以用下面方法
cls.eat = f
return cls
@eat
class Cat(object):
//猫类
def init(self, name)
self.name = name
if name == 'main':
cat = Cat('小黑')
cat.eat()
网友评论