Python函数式编程(三):装饰器和偏函数

时间:2020-12-11 22:41:48

Python不论是装饰器、偏函数,都是为效率而生!


装饰器(decorator)

Python的装饰器,算是它的一个特色吧

本质上,装饰器是一个返回函数的高阶函数

双层嵌套

"""定义一个能打印日志的decorator"""
def log(func):
    def wrapper(*args, **kw):
        print("Call %s():" %func.__name__)
        return func(*args, **kw)
    return wrapper
"""使用decorator"""
@log
def now():
    print('2018-3-21')
"""调用now()函数"""
>>> now()
call now():
2018-3-21

解释:Python使用@语法表示使用装饰器,把@log放到被装饰函数的定义处,相当于执行了语句:

now = log(now)  #Python一切皆对象,函数也是!

在执行上述语句(隐式的)后,原来的now函数仍然存在只是已经指向了一个新的函数,现在调用now函数将执行新的函数,即在log函数中返回的wrapper函数(附加了一条print语句)

三层嵌套

如果decorator本身需要传递参数,那就要编写一个返回decorator的高阶函数(用到嵌套函数,所以说Python真是一门十分灵活的语言):

"""定义一个本身可以传递参数的decorator"""
def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print("%s %s(): " % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator
"""这个三层嵌套的decorator用法如下"""
@log("execute")
def now():
    print("2018-3-21")
"""执行结果如下"""
>>> now()
execute now():
2018-3-21

解释:和不传递参数的两层嵌套decorator相比,三层嵌套decorator的效果是这样的:

now = log("execute")(now)   #decorator的外层参数是自己要传进来的,而内层参数(书写时在后面的那个)就是被装饰器装饰的函数名

嵌套函数由外向里,先执行log(“execute”),返回decorator函数,再调用返回的函数,参数是now函数,最终返回值是wrapper函数

函数名:name属性

被decorator装饰过的函数,函数名会被隐式的改变

在上面的栗子中,now函数的name从“now”变成了“wrapper”

这个好理解,看看前面的等式就知道了(因为返回的函数名就是wrapper)

为此,我们需要把原始的now函数的name属性复制到warpper函数中:

"""使用内置函数functools.wraps完成类似wrapper.__name__=func.__name__的功能"""
import functools

def log(func):
    @functools.wrap(func)
    def wrapper(*args, **kw):
        print("Call %s(): "% func.__name__)
        return wrapper
    return decorator

以上是装饰器(decorator)的完整代码


偏函数

学习Python函数式编程,要学会使用functools这个功能强大的模块

functools也提供了偏函数的相关功能

有点类似于『默认参数』的概念,偏函数允许将要承载的函数作为

"""使用functools模块下的partial函数创建一个偏函数"""
>>> import functools
int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85

总的来说,functools.partial的作用就是,把一个函数的某些参数给固定住(即设为默认值),返回一个新的函数

这样调用新的函数会更简单(在传递参数上)