文章目录[隐藏]
引言
functools
, itertools
, operator
是Python标准库为我们提供的支持函数式编程的三大模块,合理的使用这三个模块,我们可以写出更加简洁可读的Pythonic代码,接下来我们通过一些example来了解三大模块的使用。
functools的使用
functools是Python中很重要的模块,它提供了一些非常有用的高阶函数。高阶函数就是说一个可以接受函数作为参数或者以函数作为返回值的函数,因为Python中函数也是对象,因此很容易支持这样的函数式特性。
partial
>>> from functools imp<a>本文来源gao*daima.com搞@代#码&网6</a>ort partial>>> basetwo = partial(int, base=2)>>> basetwo('10010')18
basetwo('10010')
实际上等价于调用int('10010', base=2)
,当函数的参数个数太多的时候,可以通过使用functools.partial来创建一个新的函数来简化逻辑从而增强代码的可读性,而partial内部实际上就是通过一个简单的闭包来实现的。
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
partialmethod
partialmethod和partial类似,但是对于绑定一个非对象自身的方法
的时候,这个时候就只能使用partialmethod了,我们通过下面这个例子来看一下两者的差异。
from functools import partial, partialmethoddef standalone(self, a=1, b=2): "Standalone function" print(' called standalone with:', (self, a, b)) if self is not None: print(' self.attr =', self.attr)class MyClass: "Demonstration class for functools" def __init__(self): self.attr = 'instance attribute' method1 = functools.partialmethod(standalone) # 使用partialmethod method2 = functools.partial(standalone) # 使用partial
>>> o = MyClass()>>> o.method1() called standalone with: (<__main__.MyClass object at 0x7f46d40cc550>, 1, 2) self.attr = instance attribute# 不能使用partial>>> o.method2()Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: standalone() missing 1 required positional argument: 'self'
singledispatch
虽然Python不支持同名方法允许有不同的参数类型,但是我们可以借用singledispatch来动态指定相应的方法所接收的参数类型
,而不用把参数判断放到方法内部去判断从而降低代码的可读性。
from functools import singledispatchclass TestClass(object): @singledispatch def test_method(arg, verbose=False): if verbose: print("Let me just say,", end=" ") print(arg) @test_method.register(int) def _(arg): print("Strength in numbers, eh?", end=" ") print(arg) @test_method.register(list) def _(arg): print("Enumerate this:") for i, elem in enumerate(arg): print(i, elem)
下面通过@test_method.register(int)和@test_method.register(list)指定当test_method的第一个参数为int或者list的时候,分别调用不同的方法来进行处理。
>>> TestClass.test_method(55555) # call @test_method.register(int)Strength in numbers, eh? 55555>>> TestClass.test_method([33, 22, 11]) # call @test_method.register(list)Enumerate this:0 331 222 11>>> TestClass.test_method('hello world', verbose=True) # call defaultLet me just say, hello world