python中,functools模块文档在http://docs.python.org/library/functools.html。
这个模块定义了一下函数:
1.functools.reduce(function, iterable[, initializer])
这个函数和python中reduce函数一样。
>>> l = [1, 2, 3, 4, 5]
>>> reduce(lambda x,y:x+y, l)
15
>>> functools.reduce(lambda x,y:x+y, l)
15
2.functools.partial(func[,*args][, **keywords])
这个函数用一些默认参数包装一个可调用对象,返回结果是可调用对象。冻结原函数中的部分参数或关键字参数,简化函数调用。源码实现如下:
#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 newfunc
示例如下,int可以将一个数字字符串转换成某一进制的整数。当通过partial将进制绑定后,在使用这个功能时,直接输入一个数字字符串即可。
>>> int('10', base=2)
2
>>> int('10', base=8)
8
>>> int = partial(int, base=2)
>>> int('10')
2
>>> int('11')
3
3.functools.update_wrapper(wrapper, wrapped[, assigned][, updated])
使用update_wrapper(),将原始函数的一些参数拷贝加入到封装后的函数中。它可以把__name__、module、__doc__和__dict__都复制到封装后的函数中去。参照下面的例子,若是一般的装饰,__name__和__doc__的值是装饰函数中call_it的值;若使用update_wrapper,__name__和__doc__的值就是被装饰函数hello的值。#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import sys
def wrap(func):
def call_it(*args, **kwargs):
'''wrap func: call_it'''
print 'before_call'
return func(*args, **kwargs)
return call_it
@wrap
def hello():
'''say hello'''
print 'hello world'
from functools import update_wrapper
def wrap2(func):
def call_it(*args, **kwargs):
'''wrap func: call_it2'''
print 'before_call'
return func(*args, **kwargs)
return update_wrapper(call_it, func)
@wrap2
def hello2():
'''test hello'''
print 'hello world2'
if __name__ == '__main__':
hello()
print hello.__name__
print hello.__doc__
print
hello2()
print hello2.__name__
print hello2.__doc__
# vim: set expandtab sw=4 ts=4 sts=4:
输出
[wangzhilong@w-eng22 /data1/wangzhilong/Tmp]$ python test_wrap.py
before_call
hello world
call_it
wrap func: call_it
before_call
hello world2
hello2
test hello
4.functools.wraps(wrapped[, assigned][, updated])
这个函数式functools.update_wrapper的简写,等价于partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import sys
from functools import wraps
def wrap(func):
@wraps(func)
def call_it(*args, **kwargs):
'''wrap func: call_it2'''
print 'before_call'
return func(*args, **kwargs)
return call_it
@wrap
def hello2():
'''test hello'''
print 'hello world2'
if __name__ == '__main__':
hello2()
print hello2.__name__
print hello2.__doc__
# vim: set expandtab sw=4 ts=4 sts=4:
输出
[wangzhilong@w-eng22 /data1/wangzhilong/Tmp]$ python test_wrap.py
before_call
hello world2
hello2
test hello
5.functools.cmp_to_key(func)
将老式比较函数转换成key函数
>>> def numeric_compare(x, y):
... return x-y
...
>>> sorted([5,2,4,1,3], cmp=numeric_compare)
[1, 2, 3, 4, 5]
>>> import functools
>>> sorted([5,2,4,1,3], key=functools.cmp_to_key(numeric_compare))
[1, 2, 3, 4, 5]
6.functools.total_ordering(cls)
它是针对某个类如果定义了__lt__()、__le__()、__gt__()、__ge__()这些方法中的至少一个,使用该装饰器,则会自动的把其他的几个比较函数也实现在该类中。另外,要提供一个__eq__()函数。
#!/usr/bin/env python
# -*- vim: set expandtab sw=4 ts=4 sts=4:
import sys
import functools
@functools.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()))
print dir(Student)
a, b = Student(), Student()
a.firstname, a.lastname = 'wang', 'zhilong'
b.firstname, b.lastname = 'wang', 'zhi'
print a.__lt__(b)
print a.__gt__(b)
# vim: set expandtab sw=4 ts=4 sts=4:
[wangzhilong@w-eng22 /data1/wangzhilong/Tmp]$ python total_order.py
['__doc__', '__eq__', '__ge__', '__gt__', '__le__', '__lt__', '__module__']
False
True