小李飞刀:python请与我一起愉快的玩耍吧!
又是一段叨叨
如果总是担心能不能做到的话,那就干脆不要做了。
想做的事情还是一往无前的好,什么都不想,就努力冲冲冲吧!
装饰器
因为函数是一个对象。
所以。
__name__
属性,可以get函数的名字.
在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。本质上,decorator就是一个返回函数的高阶函数。
比如,定义一个能打印日志的decorator。
def log(func): def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper
log接受函数作为参数,要放置在函数定义处。
@log def now(): print('2015-3-25')
这样调用now()的时候,就会先打印出程序名称。
把@log
放到now()
函数的定义处,相当于执行了语句
now = log(now)
由于log()是一个decorator,返回一个函数,所以,原来的now()函数仍然存在,只是现在同名的now变量指向了新的函数,于是调用now()将执行新函数,即在log()函数中返回的wrapper()函数。【此时的now已经不是原来的now了,只是个同名的朋友】
当需要再进一步的时候,比如decorator本身需要传入参数,就需要再改造下函数。
这个三层嵌套的效果如下:
now = log('execute')(now)
但是也存在问题,因为函数的名字now.__name__
此时已经变成了wrapper,所以需要把原始函数的名称等属性复制到wrapper()中,否则一些依赖于函数签名的代码执行就会出错。
Python内置的functools.wraps
就可以用来处理这个问题。
一个完整的decorator的代码如下:
import functools def log(func): @functools.wraps(func) #记录的是传入的func的值,位置在嵌套内 def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper
或者带参数的如下。
import functools def log(text): def decorator(func): @functools.wraps(func) #记录的是传入的func的值,位置在嵌套内 def wrapper(*args, **kw): print('%s %s():' % (text, func.__name__)) return func(*args, **kw) return wrapper return decorator
@functools.wraps(func)
加上这句很重要。
相关推荐
运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算。以上实例中 7、5 和 12 是操作数。关系运算符用于计算结果是否为 true 或者 false。逻辑运算符用于测定变量或值之间的逻辑。