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
的作用就是,把一个函数的某些参数给固定住(即设为默认值),返回一个新的函数
这样调用新的函数会更简单(在传递参数上)