Pythonfunctools模块完全攻略

python

functools 模块中主要包含了一些函数装饰器和便捷的功能函数。在 Python 的交互式解释器中先导入 functools 模块,然后输入 [e for e in dir(functools) if not e.startswith('_')] 命令,即可看到该模块所包含的全部属性和函数:

>>> [e for e in dir(functools) if not e.startswith('_')]

['MappingProxyType', 'RLock', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES', 'WeakKeyDictionary', 'cmp_to_key', 

'get_cache_token', 'lru_cache', 'namedtuple', 'partial', 'partialmethod', 'recursive_repr', 'reduce', 'singledispatch',

 'total_ordering', 'update_wrapper', 'wraps']

在functools 模块中常用的函数装饰器和功能函数如下:

functools.cmp_to_key(func):将老式的比较函数(func)转换为关键字函数(key function)。在 Python 3 中比较大小、排序都是基于关键字函数的,Python 3 不支持老式的比较函数。

@functools.lru_cache(maxsize=128, typed=False):该函数装饰器使用 LRU(最近最少使用)缓存算法来缓存相对耗时的函数结果,避免传入相同的参数重复计算。同时,缓存并不会无限增长,不用的缓存会被释放。其中 maxsize 参数用于设置缓存占用的最大字节数,typed 参数用于设置将不同类型的缓存结果分开存放。

@functools.total_ordering:这个类装饰器(作用类似于函数装饰器,只是它用于修饰类)用于为类自动生成比较方法。通常来说,开发者只要提供 __lt__()、__le__()、__gt__()、__ge__() 其中之一(最好能提供 __eq__() 方法),@functools.total_ordering装饰器就会为该类生成剩下的比较方法。

functools.partial(func, *args, **keywords):该函数用于为 func 函数的部分参数指定参数值,从而得到一个转换后的函数,程序以后调用转换后的函数时,就可以少传入那些己指定值的参数。

functools.partialmethod(func, *args, **keywords):该函数与上一个函数的含义完全相同,只不过该函数用于为类中的方法设置参数值。

functools.reduce(function, iterable[, initializer]):将初始值(默认为 0,可由 initializer 参数指定)、迭代器的当前元素传入 function 函数,将计算出来的函数结果作为下一次计算的初始值、迭代器的下一个元素再次调用 function 函数……依此类推,直到迭代器的最后一个元素。

@functools.singledispatch:该函数装饰器用于实现函数对多个类型进行重载。比如同样的函数名称,为不同的参数类型提供不同的功能实现。该函数的本质就是根据参数类型的变换,将函数转向调用不同的函数。

functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES):对 wrapper 函数进行包装,使之看上去就像 wrapped(被包装)函数。

@functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES):该函数装饰器用于修饰包装函数,使包装函数看上去就像 wrapped 函数。

通过介绍不难发现,functools.update_wrapper 和 @functools.wraps 的功能是一样的,只不过前者是函数,因此需要把包装函数作为第一个参数传入;而后者是函数装饰器,因此使用该函数装饰器修饰包装函数即可,无须将包装函数作为第一个参数传入。

下面程序示范了 functiontools 棋块中部分函数或函数装饰器的用法:

from functools import *

# 以初始值(默认为0)为x,以当前序列元素为y,x+y的和作为下一次的初始值

print(reduce(lambda x,y: x + y, range(5))) # 10

print(reduce(lambda x,y: x + y, range(6))) # 15

# 设初始值为10

print(reduce(lambda x,y: x + y, range(6), 10)) # 25

print('----------------')

class User:

    def __init__(self, name):

        self.name = name

    def __repr__(self):

        return 'User[name=%s' % self.name

# 定义一个老式的大小比较函数,User的name越长,该User越大

def old_cmp(u1 , u2):

    return len(u1.name) - len(u2.name)

my_data = [User('Kotlin'), User('Swift'), User('Go'), User('Java')]

# 对my_data排序,需要关键字参数(调用cmp_to_key将old_cmp转换为关键字参数

my_data.sort(key=cmp_to_key(old_cmp))

print(my_data)

print('----------------')

@lru_cache(maxsize=32)

def factorial(n):

    print('~~计算%d的阶乘~~' % n)

    if n == 1:

        return 1

    else:

        return n * factorial(n - 1)

# 只有这行会计算,然后会缓存5、4、3、2、1的解乘

print(factorial(5))

print(factorial(3))

print(factorial(5))

print('----------------')

# int函数默认将10进制的字符串转换为整数

print(int('12345'))

# 为int函数的base参数指定参数值

basetwo = partial(int, base=2)

basetwo.__doc__ = '将二进制的字符串转换成整数'

# 相当于执行base为2的int()函数

print(basetwo('10010'))

print(int('10010', 2))

以上是 Pythonfunctools模块完全攻略 的全部内容, 来源链接: utcz.com/z/521073.html

回到顶部