functools工具函数包
>>> import functools
>>> dir(functools)
['RLock', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES', '_CacheInfo', '_HashedSeq', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_c3_merge', '_c3_mro', '_compose_mro', '_convert', '_find_impl', '_ge_from_gt', '_ge_from_le', '_ge_from_lt', '_gt_from_ge', '_gt_from_le', '_gt_from_lt', '_le_from_ge', '_le_from_gt', '_le_from_lt', '_lru_cache_wrapper', '_lt_from_ge', '_lt_from_gt', '_lt_from_le', '_make_key', 'cmp_to_key', 'get_cache_token', 'lru_cache', 'namedtuple', 'partial', 'partialmethod', 'recursive_repr', 'reduce', 'singledispatch', 'total_ordering', 'update_wrapper', 'wraps']
partial函数(偏函数)
把一个函数的某些参数设置默认值,返回一个新的函数,调用这个新函数会更简单。
import functools
def func(*args, **kwargs):
print(args)
print(kwargs)
f1 = functools.partial(func, 1, 2, 3)
f1()
# (1, 2, 3)
# {}
f1(4, 5, 6)
# (1, 2, 3, 4, 5, 6)
# {}
f1(kw1='python', kw2='django')
# (1, 2, 3)
# {'kw1': 'python', 'kw2': 'django'}
f2 = functools.partial(func, 1, kw='python')
f2()
# (1,)
# {'kw': 'python'}
f2(2, 3)
# (1, 2, 3)
# {'kw': 'python'}
f2(kw1='django')
# (1,)
# {'kw': 'python', 'kw1': 'django'}
def func(k1, k2, k3):
print(k1, k2, k3, '求和:', k1 + k2 + k3)
f = functools.partial(func, 1)
f(2, 3) # 1 2 3 求和: 6
f = functools.partial(func, 5, 8)
f(3) # 5 8 3 求和: 16
# 函数有初始值
def func(k1, k2=100, k3=200):
print(k1, k2, k3, '求和:', k1 + k2 + k3)
func(1) # 1 100 200 求和: 301
f = functools.partial(func, 2)
f() # 2 100 200 求和: 302
f(0, 0) # 2 0 0 求和: 2
f = functools.partial(func, 1)
f(2, 3) # 1 2 3 求和: 6
f = functools.partial(func, 5, 8)
f(3) # 5 8 3 求和: 16
wraps函数(装饰器)
使用装饰器时,有一些细节需要被注意。例如,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变)。这个wraps
函数的作用就是从 被修饰的函数(wrapped) 中取出一些属性值来,赋值给 修饰器函数(wrapper) 。
添加后由于函数名和函数的doc发生了改变,对测试结果有一些影响,例如:
def decorator(func):
"""decorator function"""
def wrapper():
"""wrapper function"""
print('in wrapper')
return func()
return wrapper
@decorator
def test():
"""test function"""
print('in test')
test()
print(test.__doc__)
# 如果没有加@decorator装饰器,结果:
# test function
# 使用了@decorator装饰器,相当于执行了一句test = decorator(test),结果:
# in wrapper
# in test
# wrapper function
Python的functools包中提供了一个叫wraps的装饰器来消除这样的副作用。例如:
def decorator(func):
"""decorator function"""
@functools.wraps(func)
def wrapper():
"""wrapper function"""
print('in wrapper')
return func()
return wrapper
@decorator
def test():
"""test function"""
print('in test')
test()
print(test.__doc__)
# wrapper()使用了装饰器@functools.wraps(func),结果
# in wrapper
# in test
# test function
wraps修饰器,其实就是将被修饰的函数(test)的一些属性值赋值给修饰器函数(decorator),最终让属性的显示更符合我们的直觉。
reduce函数(从左到右累计)
将可迭代对象iterable中的元素从左到右累计到接收两个参数的函数func中。例如reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
的计算等同于((((1+2)+3)+4)+5)
。
r = functools.reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
print(r) # 15