发布时间:2019-08-27 08:03:04编辑:auto阅读(1385)
(wrapperwrappedassigned = WRAPPER_ASSIGNMENTSupdated = WRAPPER_UPDATES):
类似咱们自己写的copy_preperties功能;
wrapper包装函数, wrapped被包装函数;
元组WRAPPER_ASSIGNMENTS中是要被覆盖的属性:模块名、名称、限定名、文档、参数注解
WRAPPER_ASSIGNMENTS = ()
元组WRAPPER_UPDATES中是要被更新的属性,__dict__属性字典:
WRAPPER_UPDATES = ('__dict__',)
增加一个__wrapped__属性,保留着wrapped函数;
import datetime, time, functools def logger(fn): # @copy_properties(fn) def wrap(*args, **kwargs): """This is a wrapper""" #before 功能增强 print("args={},kwargs={}".format(args, kwargs)) start = datetime.datetime.now() ret = fn(*args, **kwargs) #after 功能增强 duration = datetime.datetime.now() - start print("function {} took {}s.".format(fn.__name__, duration.total_seconds())) return ret functools.update_wrapper(wrap, fn)# 这里就等价于@copy_properties(fn) print("{} {}".format(id(wrap), id(fn)))# 这里是为了确认一下,add.__wrapped__到底是wrap,还是fn return wrap @logger def add(x, y): """This is a function""" print("======call add======") time.sleep(2) return x + y print(add.__wrapped__) print(id(add.__wrapped__))
其实按照源码来写的话,return wrap 可以直接写成return functools.update_wrapper(wrap, fn),为什么直接能这样写,自己看源码?
上面的方法,我们很少这样用,我们真正要用的是@functools.wraps(fn)
import datetime, time, functools def logger(fn): @functools.wraps(fn) def wrap(*args, **kwargs): """This is a wrapper""" start = datetime.datetime.now() ret = fn(*args, **kwargs) duration = datetime.datetime.now() - start print("function {} took {}s.".format(fn.__name__, duration.total_seconds())) return ret return wrap @logger# add = logger(add) def add(x, y): """This is a function""" print("======call add======") time.sleep(2) return x + y print(add.__name__, add.__wrapped__)
partial方法
偏函数,把函数部分的参数固定下来,相当于为部分的参数添加了一个固定的默认值,形成一个新的函数并返回;
从partial生成的新函数,是对原函数的封装;
举例说明:
import functools import inspect def add(x, y) -> int: return x + y print(inspect.signature(add)) #(x, y) -> int newadd = functools.partial(add, y=5) print(newadd(5)) print(newadd(5)) #TypeError: add() got multiple values for argument 'y' print(newadd(7, y=6)) print(newadd(y=6, x=10)) print(inspect.signature(newadd)) #这里是看一下新函数的签名,(x, *, y=5) -> int
更复杂一点:
import functools import inspect def add(x, y, *args) ->int: print(args) return x + y newadd = functools.partial(add, 1, 3, 6, 5) print(newadd(7)) print(newadd(7, 10)) # print(newadd(7, 10, y=20, x=10))### print(newadd()) print(inspect.signature(newadd))
lru_cache:
@functools.lru_cache(maxsize=128, typed=False)
least-recently-used装饰器。lru,最近最少使用,cache缓存
如果maxsize设置为None,则禁用LRU功能,并且缓存可以当无限制增长。
当maxsize是二的幂时,LRU功能执行得最好。
如果typed设置为True,则不同类型的函数参数将单独缓存。例如,f(3)和f(3.0)将被视为具有不同结果的不同调用。
import functools, time @functools.lru_cache() def add(x, y, z=3): time.sleep(z) return x + y print(add(4, 5)) print(add(4, 5)) print(add(4, 5)) print(add(4, 5)) #在ipython里看的效果会更清楚
上一篇: 安装homeassistant+pyth
下一篇: python查看df并输出
47882
46450
37336
34773
29348
26011
24961
19979
19582
18076
5821°
6449°
5962°
5988°
7096°
5937°
5981°
6472°
6437°
7818°