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
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语言内核的标准库之一,通过使用它提供的函数,我们可以更加方便的对函数进行管理和操作,进而提高我们的编程效率。