Python3标准库之functools管理函数的工具详解

1. functools模块简介

Python是一门高级语言,拥有很多有用的模块。一个常用的模块是functools,是Python语言内核的标准库之一,在Python 2.5中被引入。它采用高阶函数的思想,就是可以将一个函数作为参数传递到另一个函数中,这样可以更加灵活的组合函数,方便程序员编写高效且可读性更好的代码。functools模块包含许多有用的工具函数,这些函数可以帮助我们更方便地管理函数。

2. functools模块的核心函数

2.1 partial函数

partial函数用于创建新的函数,固定原函数的部分参数,使得调用时更加简单。例如:

from functools import partial

def func(x,y,z):

return x + y + z

new_func = partial(func, y=2, z=3)

print(new_func(1)) # 输出6

partial函数将输入的函数以及传入的参数存储起来,然后返回一个新的函数对象,这个新的函数对象可以像原函数一样被调用。partial函数用于简化函数调用,特别是在需要重复调用相同函数的时候。

2.2 update_wrapper函数

update_wrapper函数主要用于将某个函数的属性复制到另外的一个函数上。这个函数通常用于装饰器,通过装饰器将一个函数的属性复制到另外的函数上,这样就不会由于装饰器的作用而使原函数的属性丢失。例如:

from functools import update_wrapper

def my_decorator(f):

def wrapper(*args, **kw):

print('Something is happening before the function is called.')

return f(*args, **kw)

update_wrapper(wrapper, f)

return wrapper

@my_decorator

def say_hello():

print('Hello!')

print(say_hello.__name__) # 输出'say_hello'

以上代码中,my_decorator函数是使用装饰器语法来使用的。update_wrapper函数在这里的作用是把say_hello函数的属性,比如__name__等,赋值给wrapper函数。这样的话,在使用say_hello原函数的时候,依旧能够保持其原函数的特性。

2.3 wraps函数

在使用装饰器时,有些函数会被其他模块所使用,这个时候可以使用functools.wraps函数,它能够帮助我们把装饰器函数的属性赋值给被装饰的函数,这样可以更加方便地使用被装饰函数的元信息。

from functools import wraps

def my_decorator(f):

@wraps(f)

def wrapper(*args, **kw):

print('Something is happening before the function is called.')

return f(*args, **kw)

return wrapper

@my_decorator

def say_hello():

'''This is a docstring'''

print('Hello!')

print(say_hello.__doc__) # 输出 'This is a docstring'

以上代码中,我们使用了functools.wraps函数来保留原函数的元信息。

2.4 lru_cache函数

lru_cache的作用是缓存最近使用的函数结果。当函数被调用时,它将使用一个字典来存储这个函数的参数及其结果,当相同的参数再次被调用时,函数不会被再次执行,直接从字典中返回结果。如果缓存被填满了,这个函数会自动替换掉最少使用的一个结果。lru_cache函数可以大大提高函数的运行效率,特别是对于那些计算量大的函数,这个函数非常有用。

from functools import lru_cache

@lru_cache(maxsize=10)

def fib(n):

if n<2:

return n

return fib(n-1) + fib(n-2)

print([fib(n) for n in range(16)]) # 输出[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]

以上代码中,我们使用了lru_cache函数来缓存fib函数的结果。由于cache的大小为10,所以只有前10个结果会被缓存。这个函数非常适用于递归函数,因为它可以避免递归带来的重复计算。

3. functools模块的其他函数

3.1 reduce函数

reduce函数的作用是将一个函数作用在一个序列上,这个序列必须是可迭代的。例如:

from functools import reduce

def add(x, y):

return x + y

print(reduce(add, [1, 2, 3, 4])) # 输出10

以上代码中,我们用reduce函数实现了序列求和的功能。

3.2 cmp_to_key函数

cmp_to_key是把一个比较函数转化为一个key函数,这个key函数可以被传递到sorted和min/max等函数中。

from functools import cmp_to_key

def compare(x, y):

if x < y:

return -1

elif x > y:

return 1

else:

return 0

a = [4,1,3,6,7,2,9,5,8]

print(sorted(a, key=cmp_to_key(compare)))

以上代码中,我们定义了一个比较函数,然后使用cmp_to_key函数将它转化为一个key函数,并把这个key函数传递给sorted函数。这样就可以对列表按照我们的需求进行排序。

3.3 total_ordering函数

total_ordering函数是一个类装饰器,它可以把一个类转化为一个完全序列化的类。也就是说,通过这个函数,一个类可以直接支持x=y和x>y这些操作符。这个函数非常适合那些没有实现全部比较运算符的类。

from functools import total_ordering

@total_ordering

class School:

def __init__(self, name, age):

self.name = name

self.age = age

def __eq__(self, other):

return self.age == other.age

def __lt__(self, other):

return self.age < other.age

s1 = School('John', 18)

s2 = School('Susan', 20)

print(s1 == s2) # 输出False

以上代码中,我们使用了total_ordering函数来为School类实现全部比较运算符。

3.4 singledispatch函数

singledispatch函数是Python3.4版本中新增的函数,它是用于实现以单分派泛型函数类型的函数。如果有些函数希望根据参数类型的不同采取不同的行为,这时候就可以使用singledispatch函数了。

from functools import singledispatch

@singledispatch

def func(value):

print('This is a general function.')

@func.register(int)

def _(value):

print('This is an integer.')

@func.register(str)

def _(value):

print('This is a string.')

func(1) # 输出 'This is an integer.'

func('abc') # 输出 'This is a string.'

以上代码中,我们定义了一个通用函数func,并用装饰器@singledispatch为它添加了两个参数类型的不同实现版本。当使用通用函数func传入参数时,Python会根据参数类型的不同,自动调用对应参数类型的函数实现。

4. 总结

在本文中,我们简要的介绍了functools模块,分别讲解了partial、update_wrapper、wraps、lru_cache、reduce、cmp_to_key、total_ordering和singledispatch等核心函数的使用方法,并且列举了一些具有实际用途的例子。functools模块是Python语言内核的标准库之一,通过使用它提供的函数,我们可以更加方便的对函数进行管理和操作,进而提高我们的编程效率。

后端开发标签