装饰器decorator
decorator 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数。例如,现在存在一个函数A(),但是里面没有Log,没有打印出相关的信息,现在我又想添加一个Log方法,就可以使用装饰器了,这样的话就不用直接修改源代码。只需要只用@标识符
import time
def performance(f):
def fn(*args, **kw):
# *args和**kw可以保证任意参数个数的函数都可以被装饰
# 如果只有一个参数,被装饰的函数有2个参数就会报错
print 'call factorial() in'
return f(*args, **kw)
return fn
# 通过添加 @ + 函数名来表示装饰器
@performance
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
# call factorial() in
# 3628800
编写带参数decorator : @log(‘DEBUG’)
不带参的装饰器需要2层解析,第一层也就是最外面的一层用于接受函数,第二层用于创建一个新函数,并将结果返回。
而带参的装饰器需要3层解析,第一层用于获取参数,第二层用于接受函数,第三层用于创建一个新函数,并将结果返回。
import functools
def log(options):
def printlog(f):
@functools.wraps(f)
#functools用于复制原函数的一些必要属性到新函数上,下一节具体讲解
def wrap(*args, **kw):
if options == 'DEBUG':
print 'This is DEBUG'
else:
print 'This is OTHERS'
return f(*args, **kw)
return wrap
return printlog
@log('DEBUG')
def factorial(n):
return 'Number is ', n
@log('RELEASE')
def factorial2():
print ''
print factorial2()
print factorial(10)
# This is OTHERS
#
# None
# This is DEBUG
# ('Number is ', 10)
完善装饰器 functools
产生了一个新的装饰器之后,所在函数的一些基本属性例如name和doc会被新函数的属性name和doc取代。这肯定不是我们需要的,因为有的时候有的东西是基于函数名或者函数的一些其他属性来绑定的。
所以在创建新函数的时候就需要将原函数的一些基本属性复制到新函数中。
Python自带一个复制的库-> functools
首先引用包 import functools
然后在第二层解析与第三层解析中间添加-> @functools.wraps(f)
如果是无参的装饰器就在第一层和第二层解析中间添加
通俗一点:就是在获取了function参数之后添加该方法