又是一段叨叨
如果总是担心能不能做到的话,那就干脆不要做了。
想做的事情还是一往无前的好,什么都不想,就努力冲冲冲吧!
装饰器
因为函数是一个对象。
所以。
-
__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)
加上这句很重要。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。