2018-6-5
先看一个例子:
>>> def now():
print('2015-3-25')
>>> f = now
>>> f()
2015-3-25
现在我们可以用__name__
拿到函数的名字。
如果现在要增强now()
的功能,例如在函数调用前后自动打印日志,但又不希望修改now()
函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
—————-此处不能明白,先略过
下面给出的是定义一个能打印日志的decorator
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
@log
#上面的@log相当于执行了语句
#now = log(now)
def now():
print('2015-3-25')
>>> now()
call now():
2015-3-25
这段代码实现的是调用now()
函数,实现:
1、运行now()
函数本身
2、在运行now()
函数之前打印一行日志:call now():
装饰器给出的解释为:
由于log()是一个decorator,返回一个函数,所以,原来的now()函数仍然存在,只是现在同名的now变量指向了新的函数,于是调用now()将执行新函数,即在log()函数中返回的wrapper()函数。
wrapper()函数的参数定义是(*args, **kw),因此,wrapper()函数可以接受任意参数的调用。在wrapper()函数内,首先打印日志,再紧接着调用原始函数。
我的理解这段代码是这样运行的:
1.@log
即now = log(now)
log(now)
的意思是:now()
函数传入log()
中,返回一个wrapper()
函数。这个wrapper()
函数是什么呢?我们看print('call %s():' % func.__name__)
,其中有一个%s
,其意思是将%func.__name__
插入到%s
这个位置,也就变成了call now():
。然后一个新的变量now指向了这个返回的wrapper()
函数。
2.在wrapper()
函数内部,先完成了打印日志的功能,然后return func(*args, **kw)
中调用了now()
函数,即实现print('2015-3-25')
。
2018-6-6
啊~五环
今天看到一篇称@log
这样的东西为语法糖的文章。
可以用来精简装饰器代码。
Python装饰器——田小计划
如果装饰器本身需要支持参数,那么装饰器就需要多一层的内嵌函数。
装饰器调用顺序
装饰器是可叠加的。对于Python中的”@”语法糖,装饰器的调用顺序与使用 @ 语法糖声明的顺序相反。