在不改变原函数的情况下为原函数扩展
装饰器函数都是要闭包的
向装饰器函数传入要被装饰的函数
被装饰的函数在调用时相当于调用装饰器函数,并向其中传入了被装饰的函数作为参数。
无参数
def func_out(func):
def func_in():
print('扩展函数')
func()
return func_in
@func_out
def func_main():
print("主体函数")
func_main()
有参数
参数要层层传递下去
def func_out(func):
def func_in(obj):
print('扩展函数')
func(obj)
return func_in
@func_out
def func_main(char):
print("主体函数",char)
func_main('NB')
多参数
def func_out(func):
def func_in(*args,**kwargs):
print('扩展函数')
func(args,kwargs)
return func_in
@func_out
def func_main(*args,**kwargs):
print("主体函数",args,kwargs)
func_main('NB',a='NB')
等一下,这样就出问题了!
扩展函数
主体函数 (('NB',), {'a': 'NB'}) {}
所以参数都传进args
里面了!
在传参时要用*args
和**kwargs
进行传参。
正确用法
def func_out(func):
def func_in(*args,**kwargs):
print('扩展函数')
func(*args,**kwargs)
return func_in
@func_out
def func_main(*args,**kwargs):
print("主体函数",args,kwargs)
func_main('NB',a='NB')
返回值
要想返回值,必须装饰器和主题函数都一起return
def func_out(func):
def func_in(*args,**kwargs):
print('扩展函数')
return func(*args,**kwargs) # 装饰器return
return func_in
@func_out
def func_main(*args,**kwargs):
print("主体函数",args,kwargs)
return args,kwargs # 函数中的return
print(func_main('NB',a='NB'))
在装饰器上设置外部变量
需要在外面再套层壳
def test(arg):
print(arg)
"""这里进入正常的装饰器"""
def func_out(func):
def func_in(*args,**kwargs):
print('扩展函数')
return func(*args,**kwargs)
return func_in
return func_out
@test("666")
def func_main(*args,**kwargs):
print("主体函数",args,kwargs)
return args,kwargs
print(func_main('NB',a='NB'))
多重装饰器
在前面多加几个装饰器就行啦,靠近被装饰函数的会先被执行(就近原则)
@func_1
@func_2
def function():
pass
类装饰器
使用类为函数做装饰
# 使用类为函数作装饰
class Test(object):
def __init__(self):
print("__init__方法")
def func(self):
print("方法1")
test = Test()
test()
执行时会报错TypeError: 'Test' object is not callable
我们为它加上__call__()
方法,使它可以被执行。
# 使用类为函数作装饰
class Test(object):
def __init__(self):
print("__init__方法")
def func(self):
print("方法1")
def __call__(self, *args, **kwds):
print("__call__方法")
test = Test()
test()
直接调用test()先在它会执行__init__
方法,然后执行__call__
方法。
# 使用类为函数作装饰
class Test(object):
def __init__(self,func):
print("__init__方法",func)
def func(self):
print("func方法")
def __call__(self, *args, **kwds):
print("__call__方法")
@Test
def function():
print("function函数")
function()
实际上用@Test
装饰函数相当于function = Test(function)
之后我们调用的function()实际上是一个类,它执行了自己的__init__
方法和__call__
方法。
class Test(object):
def __init__(self,func):
print("__init__方法",func)
self.func = func
def func(self):
print("func方法")
def __call__(self, *args, **kwds):
print("__call__方法")
self.func()
@Test
def function():
print("function函数")
function()
我们把传入的function储存一下,并在__call__
方法中调用