英文原文出自:https://docs.python.org/2/library/functools.html
functools 是一系列高阶函数的集合,这些函数可以接受其他函数作为参数或者返回其他函数。一般说来,凡是可被调用的对象,都可以当成这个模块的作用对象。
functools 模块定义了下面的一系列函数:
functools.
cmp_to_key
(func)
cmp_to_key可以将老式风格的比较函数转换成比较关键字函数。这个函数用在接收比较关键字函数作为参数的函数中(比如 sorted()
, min()
, max()
, heapq.nlargest()
, heapq.nsmallest()
, itertools.groupby()
)。因为在Python3中不再支持老式风格的比较函数,这个函数也常被当成把python2的函数转向python3的工具。
老式风格的比较函数是指,接收两个参数进行比较,如果一个前者小于后者返回一个负数,前者等于后者返回0,前者大于后者返回一个正数。比较关键字函数是指接收一个参数,返回另外一个结果作为排序的关键字。
应用举例:
from functools import cmp_to_key
def cmfunc(x,y):
if x>y:
return 1
elif x==y:
return 0
else:
return -1
seq=[2,1,4,5,3]
seq = sorted(seq,key=cmp_to_key(cmfunc))
for r in seq:
print r
输出结果:
hyman@hyman-VirtualBox:~/projects/PythonTs$ python cmp_to_keyTs.py
1
2
3
4
5
查看更多排序的例子或者相关文档请查看
Sorting HOW TO
.
functools.
total_ordering
(cls)
如果一个类中含有一个以上的用于比较的方法,这个类级别的修饰器会补充剩下的部分用于比较的方法,它简化了在类中定义比较方法的繁重工作。
这个被修饰的类必须定义以下方法之一 __lt__()
, __le__()
, __gt__()
, or __ge__()。另外,该类也必须实现
__eq__()
方法。
@total_ordering
class Student:
def __eq__(self, other):
return ((self.lastname.lower(), self.firstname.lower()) ==
(other.lastname.lower(), other.firstname.lower()))
def __lt__(self, other):
return ((self.lastname.lower(), self.firstname.lower()) <
(other.lastname.lower(), other.firstname.lower()))
我们定义了Student类,只声明了__eq__和__lt__方法,当Student类被total_ordering修饰后,使用dir查看Student的属性,其他剩余的比较函数都被自动定义:
>>> from total_orderingTs import Student
>>> dir(Student)
['__doc__', '__eq__', '__ge__', '__gt__', '__le__', '__lt__', '__module__']
>>>
functools.
reduce
(function, iterable[, initializer])
这个函数和reduce的功能一样,它在functools模块创建只是为了使python3向前兼容。
使用举例:
from functools import reduce
def add(x,y):
return x+y
print reduce(add,[1,2,3,4,5])
reduce的功能是将list中的前两个值作为参数传给add函数,然后将add的结果和第三个值再次传给add函数,以此类推,最终返回一个结果:
hyman@hyman-VirtualBox:~/projects/PythonTs$ python reduceTs.py
15
functools.
partial
(func[,*args][, **keywords])¶
返回一个新的partial(偏函数)对象,partial被调用时就像传给它的func函数带着参数args和keywords被调用一样。如果func也附带了自己的参数,那么它的参数将被追加至args或者keywords中。大概等价于以下代码:
def partial(func, *args, **keywords):
def newfunc(*fargs, **fkeywords):
newkeywords = keywords.copy()
newkeywords.update(fkeywords)
return func(*(args + fargs), **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfun
partial()通过"冻结"一个函数的部分参数而获取一个偏函数对象,相当于简化了原函数的签名。比如说 partial()可以创建一个行为类似于base为2的int()函数:
>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18
应用举例:
from functools import partial
def add(x,y,z):
return x+y+z
newadd=partial(add,y=1,z=2)
print newadd(3)
print newadd(55555)
我们用partial定义新的函数newadd,但是简化了参数列表,只传入一个参数即可。
functools.
update_wrapper
(wrapper, wrapped[, assigned][, updated])
使修饰函数更加符合被修饰函数。该函数中的后面可选参数是两组元组,前者用来指定从被修饰函数中获取哪些属性给修饰函数,后者用来指定修饰函数中哪些属性需要更新和被修饰函数一致。这些参数的默认值都是模块级别的约束,如WRAPPER_ASSIGNMENTS (在修饰函数中增加 __name__, __module__ 和 __doc__这些文档属性)和WRAPPER_UPDATES (更新修饰函数的__dict__属性)
这个函数最主要的用处就是用在装饰器中。如果装饰器中的修饰函数没有被更新,装饰器的返回函数的元数据将会映射修饰函数而非被修饰函数。
functools.
wraps
(wrapped[, assigned][, updated])
from functools import wraps
def decoratorWithoutWraps(f):
def wrapper_func(args):
"""wrapper doc"""
return f(args)
return wrapper_func
@decoratorWithoutWraps
def wrapped_func1(args):
"""wrapped1 doc"""
pass
def decoratorWithWraps(f):
@wraps(f)
def wrapper_func():
"""wrapper doc"""
return f()
return wrapper_func
@decoratorWithWraps
def wrapped_func2():
"""wrapped2 doc"""
pass
if __name__ =='__main__':
#without @wraps
print wrapped_func1.__name__
print wrapped_func1.__doc__
#with @wraps
print wrapped_func2.__name__
print wrapped_func2.__doc__
hyman@hyman-VirtualBox:~/projects/PythonTs$ python wrapperTs.py
wrapper_func
wrapper doc
wrapped_func2
wrapped2 doc
对于修饰器函数前没有使用@wraps的,打印出来的结果是定义的修饰器函数的__name__和__doc__,而对于修饰器前使用@wraps的,打印出来的是被修饰函数的
__name__和__doc__,显然后者才是我们期望的。
Github位置:
https://github.com/HymanLiuTS/PythonTs
克隆本项目:
git clone git@github.com:HymanLiuTS/PythonTs.git
获取本文源代码:
git checkout PL02