Python模块–functools工具函数包

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

转载自:https://blog.csdn.net/weixin_34326558/article/details/86843682

You may also like...