【装饰器】
1、最简单的Decorator。
def author(f): def addName(): print('My name is xkfx. ') f() return addName @author def helloWorld(): print('Hello, World')
把@log
放到now()
函数的定义处,相当于执行了语句:helloWorld = author(helloWorld)。
>>> helloWorld() My name is xkfx. Hello, World
这个时候查看函数的名字会发现
>>> helloWorld.__name__ 'addName'
2、稍微修改一下
def author(f): def addName(): print('My name is xkfx.[edition-2] ') return f() return addName @author def helloWorld(): print('Hello, World')
>>> helloWorld() My name is xkfx.[edition-2] Hello, World
将直接调用f();改为return f();执行效果是一样的,先打印author name然后执行原函数。
3、这个时候希望由用户输入author名,也就是包装器要接收一个字符串参数,那该怎么办?这就需要一个嵌套的decorator:
def author(authorName): def decorator(func): def wrapper(*args, **kw): # wrapper是包装纸的意思 print("author:" + authorName) return func() # 调用原函数,注意是有括号的 return wrapper # 返回包装后的函数 return decorator # 返回真正的包装器
>>> from test import author >>> @author('xkfx') ... def printHello(): ... print('Hello ') ... >>> printHello() author:xkfx Hello
查看被包装后的函数名:
>>> printHello.__name__ 'wrapper'
需要把原始函数的__name__
等属性复制到wrapper()
函数中,否则,有些依赖函数签名的代码执行就会出错。而做这件事情本身也属于“拓展函数功能”的范畴,用Python库内置的装饰器完成就可以了。只需记住在定义wrapper()
的前面加上@functools.wraps(func)
即可,如下所示:
import functools def author(authorName): def decorator(func): @functools.wraps(func) def wrapper(*args, **kw): # wrapper是包装纸的意思 print("author:" + authorName) return func() # 调用原函数,注意是有括号的 return wrapper # 返回包装后的函数 return decorator # 返回真正的包装器
再走一遍流程:
>>> printHello.__name__ 'printHello'
4、练习。
import functools def log(func): @functools.wraps(func) def wrapper(*args, **kw): print('begin call') result = func(*args, **kw) print('after call') return result return wrapper @log def f(): pass
需求二不会做。
【偏函数】
当函数的参数太多的时候,可以选择将部分参数固定来简化函数,固定的方式就是使用functools模块中的partial函数。
一个简单的例子,固定谈话对象:
def say(words, name): print(words + ',' + name)
原函数需要两个参数:
>>> say('hello', 'xkfx') hello,xkfx
经简化后得到的“偏”函数只需要传入一个参数就够了:
>>> say2 = functools.partial(say, name='xkfx') >>> say2('hi') hi,xkfx
当然固定多个参数肯定是可行的,(实际上是将要固定关键字参数传入了一个隐式的dict)
>>> say2 = functools.partial(say, name='xkfx', age=19) >>> say2('hi') hi,xkfx Your age is 19