前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python的functools模块

Python的functools模块

作者头像
py3study
发布2020-01-09 16:52:53
3600
发布2020-01-09 16:52:53
举报
文章被收录于专栏:python3python3
代码语言:javascript
复制
(wrapperwrappedassigned = WRAPPER_ASSIGNMENTSupdated = WRAPPER_UPDATES):

  类似咱们自己写的copy_preperties功能;

  wrapper包装函数, wrapped被包装函数;

  元组WRAPPER_ASSIGNMENTS中是要被覆盖的属性:模块名、名称、限定名、文档、参数注解

代码语言:javascript
复制
WRAPPER_ASSIGNMENTS = ()

  元组WRAPPER_UPDATES中是要被更新的属性,__dict__属性字典:  

代码语言:javascript
复制
WRAPPER_UPDATES = ('__dict__',)

  增加一个__wrapped__属性,保留着wrapped函数;


代码语言:javascript
复制
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)

代码语言:javascript
复制
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生成的新函数,是对原函数的封装;

举例说明:

代码语言:javascript
复制
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

更复杂一点:

代码语言:javascript
复制
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)将被视为具有不同结果的不同调用。

代码语言:javascript
复制
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里看的效果会更清楚
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-08-27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档