学习廖雪峰老师的教程做的笔记
当我们不想改变原有函数的定义,又想对函数功能进行增强,可以使用Decorator修饰器进行动态增强。
举例:
def date():
print('2018-08-01')
我们想对date()函数进行增强:在运行的时候加上日志
func.name:函数的name属性,可以拿到函数的名字
def log(func): #因为log是一个Decorator,所以可以接收一个函数作为参数,并返回一个函数
def demo(*args, **kw): #传入参数是*args, **kw,可以接收任意参数,所以下面的func(*args, **kw)可以调用
print('当前调用方法 %s()返回结果:' % func.__name__)
return func(*args, **kw)
return demo
@log #使用python的@语法,把decorator置于函数的定义处
def date():
print('2018-08-01')
date()
执行结果:
D:\front-end\python>python decorator.py
当前调用 date()函数返回结果:
2018-08-01
如果log()函数需要传入参数,即decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数
def log(text):
def decorator(func):
def demo(*args, **kw):
print('log()参数: %s 当前调用 %s()函数:' % (text, func.__name__))
return func(*args, **kw)
return demo
return decorator
@log('execute')
def date():
print('2018-08-01')
date()
执行结果:
D:\front-end\python>python decorator.py
log()参数: execute 当前调用 date()函数:
2018-08-01
这样会出现一个问题:
>>> date.__name__ #__name__属性获取的是demo,而不是date
'demo'
因为返回的那个demo()函数名字就是’demo’,所以,需要把原始函数的name等属性复制到demo()函数中,否则,有些依赖函数签名的代码执行就会出错,Python内置的functools.wraps可以把原始函数的name等属性复制到新函数中,只要引入functools模块之后,在新函数头上加上@functools.wraps(func)即可,举例:
>>> import functools
>>> def log(text):
... def decorator(func):
... @functools.wraps(func)
... def demo(*args, **kw):
... print('log()参数: %s 当前调用 %s()函数:' % (text, func.__name__))
... return func(*args, **kw)
... return demo
... return decorator
...
>>> @log('execute')
... def date():
... print('2018-08-01')
...
>>> date()
log()参数: execute 当前调用 date()函数:
2018-08-01
>>> date.__name__
'date'
>>>