python的functools模块

名称解释
lru_cache缓存函数执行的结果, 注意被装饰的函数, 只接受不可变类型的传参
partial在不改变原函数本身的情况下, 固定原函数的某些参数, 生成一个新的函数
wraps将被装饰器装饰过的函数的一些属性, 也copy到闭包环境中
update_wrapper同wraps
singledispatch将函数绑定, 通过传参数类型不同, 执行不同的函数

1.lru_cache

1.1 使用场景

当某个函数操作耗时时间较长,但每次调用时传入的参数相同时,可以将结果放置到缓存中,再次执行时,可以跳过执行函数,直接在缓存中获取结果

1.2 代码原理

from functools import lru_cache

# maxsize 为缓存数量, 一般为2的幂性能最佳, typed表示相同参数的不同类型参数,算作不同的缓存
@lru_cache(maxsize=1, typed=True)
def func(var):
    print(var + 1)
    return var

print(func(1))
print(func(1))
# 查看缓存
print(func.cache_info())

print(func(2))
print(func.cache_info())

# 清空缓存
func.cache_clear()
print(func.cache_info())

# 以上代码执行结果为:
# 第一次调用时,执行了func函数中的print, 第二次传入同样的参数时, 没有执行print,而是从缓存中直接获取结果
2
1
1

# hits为缓存命中次数, misses为缓存数量
CacheInfo(hits=1, misses=1, maxsize=1, currsize=1)
3
2
CacheInfo(hits=1, misses=2, maxsize=1, currsize=1)

# 清空缓存后, 为0
CacheInfo(hits=0, misses=0, maxsize=1, currsize=0)

2.partial

2.1 使用场景

当我们频繁调用某个函数时,其中函数的某些参数是已知的固定值, 如果将这些参数写成 var=xxx 的默认参数形式时的缺陷是, 每次增删改参数时都要改动函数本身,不够灵活

2.2 代码原理

# 当我们想要实现一个功能: 每次计算某些数字 + 100 的结果

# 第一种做法:该写法导致每次传入100,代码冗余
def add(*args):
    return sum(args)

print(add(1, 2, 3) + 100)
print(add(5, 5, 5) + 100)

# 第二种做法: 该写法导致想要计算不同结果时 要修改函数本身, 不够灵活
def add(*args):
    # 对传入的数值相加后,再加上100返回
    return sum(args) + 100

print(add(1, 2, 3))  # 106
print(add(5, 5, 5))  # 115 

# 第三种做法: 该写法导致函数参数固定, 不够灵活
def add(*args, num=100)
	return sum(args) + num

print(add(1, 2, 3))
print(add(5, 5, 5))

# 最后使用partial改写该函数
from functools import partial

def add(*args)
	return sum(args)

p1 = partial(add, 100) # 将100提前传入函数
p1((1, 2, 3))
p2 = partial(add, 200) # 将200提前传入函数, 体现了函数的灵活性
p2((1, 2, 3))

2.3 使用注意事项

from functools import partial

def func(a, b, c, d):
    print(a, b, c, d)

func(1, 2, 3, 4) # 普通传参

p1 = partial(func, 1, 2, 3, 4)
p1() # 1.不需要传入参数, 因为已经提前固定

p2 = partial(func, 1, 2)
p2(3, 4) # 2.提前固定了a, b参数,但是c, d参数需要传参

p3 = partial(func, b=2, d=4)
p3(1, c=3) 
p3(a=1, c=3) # 3.如果关键字参数不是连续的, 则调用函数时, 前面的参数使用位置参数, 后面的参数使用关键字参数,或者同时使用关键字参数

3.wraps

3.1 使用场景

当函数被装饰器装饰时, 该函数的属性会发生改变, 不再表示原函数, 如果想要展示原函数的属性,则需要使用wrapper

3.2 代码原理

from functools import wraps

def wrapper_func(func):
    
    @wraps(func) # 这里使用wraps, 将原func函数的属性继承过来
    def wrapper_func_core(*args, **kwargs):
        """这里是wrapper_func_core函数备注"""
        
        print("这里是装饰器对func函数新添加的 打印功能")
        
        return func()
        
    return wrapper_func_core

@wrapper_func
def func():
    """这里是func的函数备注"""
    pass

print(func.__doc__) # 如果没有wraps, 则将显示wrapper_func_core备注, 而不是func备注
print(func.__name__)
print(func.__module__)
print(func.__dict__)

4. update_wrapper

同wraps作用相同, 但是wraps更简便

5.singledispatch

from functools import singledispatch


@singledispatch
def show(var):
    print(f"show函数{var}")
    
@show.register(str)
def f_test(text):
    print(f"text函数{text}")
    
@show.register(int)
def f_int(n):
    print(f"inte函数{n}")


@show.register(list)
def f_list(li):
    print(f"list函数{li}")
    
show([]) # 这里调用show函数时, 会根据传参的类型, 执行f_list函数
show({}) # 如果show函数没有绑定 参数类型的函数, 则执行show函数本身
f_test(11) # 被show函数绑定的函数, 也可以正常使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值