发布时间:2019-08-27 08:03:04编辑:auto阅读(1875)
(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并输出
51234
50667
41274
38090
32555
29458
28318
23183
23145
21474
1548°
2267°
1878°
1816°
2120°
1863°
2549°
4276°
4137°
2947°