前面碰到了装饰器的一些内容,这里总结一下。
要想对python更深入理解一些,装饰器是必须要掌握的内容。
闭包
必须说一下闭包这个概念,python的装饰器是python的闭包实现。
说一个通俗的理解,闭包就是能够读取其他函数的内部变量的函数,闭包是函数内部和外部链接的一个桥梁(这句话是百度百科摘过来的,我觉得不错)。我们也都知道python的的命名空间LEGB:查找顺序
L:local, 局部变量,函数结束,L也就没了
E:encolosing,这就是闭包的函数域
G:global,全局的变量
B:build in的内嵌的,比如系统关键字,type,int之类的
global num1
num1 = 1 # 全局
def test():
num1 = 2 # 局部
print num1
num2 = 3 # enclosing
num3 = 4 # local
def func():
print num2
return func
fun = test()
fun()
print num1
print int # build in
装饰器
装饰器对函数或类进行“装饰”包裹,然后给对应的函数一些附加的功能,可以极大增加复用。
比如我们说一个add的函数,如果我们要在add中增加log,我们可以这么实现
def add(x, y):
print "add operation"
return x + y
这种方式太麻烦,如果很多函数都要加log,那就要增加很多很多,不利于维护。
或者我们可以这样
def logger(func):
print "logger"
return func
print logger(add)(1, 2)
但是这样似乎还是欠缺点,每次都要把func传入函数内,这个似乎更像是包裹函数了。
接下来我们尝试用装饰器,装饰器其实就是一个闭包函数,其实就是一个函数
def log(func):
def wrapper(*args,**kwargs):
print "logggggggggg"
return func(*args,**kwargs)
return wrapper
@log
def hello():
print "keke"
hello()
这里可能会说,我希望log是可以传参的,装饰器也是可以解决这个问题的
def logger(info):
def log(func):
def wrapper(*args,**kwargs):
print info
return func(*args, **kwargs)
return wrapper
return log
@logger(info = "这是什么")
def hello():
print "hello"
hello()
如果你在对这个研究深入一点的话,你会发现有点问题,那就是装饰器其实返回的是另外一个函数,这个会将原先函数的元数据信息给冲刷掉。
比如:
def log(func):
def wrapper(*args,**kwargs):
print func.__name__
return func(*args,**kwargs)
return wrapper
@log
def hello():
print "hello"
hello()
tmp = log(hello)
print tmp.__name__
这两个是不一样的,我们可以用functools的wraps来再装饰一次,把func的元信息保存。
from functools import wraps
def log(func):
@wraps(func)
def wrapper(*args,**kwargs):
print func.__name__
return func(*args,**kwargs)
return wrapper
@log
def hello():
print "hello"
hello()
tmp = log(hello)
print tmp.__name__
除了上述这些之外,还有类装饰器,
类装饰器的好处,我也大概复制下其他人的说法(灵活度大、高内聚、封装性等优点),其实说白了,就是累装饰器比函数灵活度更高,更好用。
类装饰器主要利用的是__call__这个内置函数,只要对象具有该内置函数,则可以执行。
class Wrapper(object):
def __init__(self,func):
self._func = func
def __call__(self, *args, **kwargs):
print "begin"
ret = self._func(*args, **kwargs)
print "end"
return ret
@Wrapper
def test():
return "wo shi test"
print test()
来源:CSDN
作者:排山和倒海
链接:https://blog.csdn.net/wangqing008/article/details/103889082