装饰器的几种形式
1.无参无返回值
def setFunc(func):
def wrapper():
print('start')
func()
print('end')
return wrapper
@setFunc
def show():
print('show')
show() #在不改变原函数调用释放下 添加了功能
#
start
show
end
2.无参有返回值
def setFunc(func):
def wrapper():
print('start')
func() # 若改为 return func() 则输出 start show 因为遇到return终止end不输出
print('end')
return wrapper
@setFunc
def show():
return 'show'
print(show()) # 返回值 show 在 装饰器中 没有输出
start
end
None #print wrapper为空 None
3.有参无返回值
def setFunc(func):
def wrapper(s):
print('start')
func(s)
print('end')
return wrapper
@setFunc
def show(s):
print('hello %s' %s)
show('zucc')
start
hello zucc
end
4.有参有返回值
def setFunc(func):
def wrapper(x, y):
print('start')
return func(x, y) #return后终止
print('end') #end 不会输出
return wrapper
@setFunc
def myAdd(x, y):
return x+y
print(myAdd(1, 2))
start
3
万能装饰器
根据被装饰函数定义的不同,分出了四种形式。
能不能实现一种,适用于任何形式函数定义的装饰器?
通过可变参数(*args/**kwargs)来接收不同的参数类型
def setFunc(func):
def wrapper(*args, **kwargs):
print('Wrapper context.')
return func(*args, **kwargs)
return wrapper
@setFunc
def func(name, age, job = 'it'):
print(name, age,'student')
func('Tom',18,)
@setFunc
def funcc(x, y):
return x*y
print(funcc(3, 4))
@setFunc
def demo(a, b, *c, **d):
print((a, b))
print(c)
print(d)
demo('zu','cc', 1999, 1, 1,school = 'zucc')
Wrapper context.
Tom 18 student
Wrapper context.
12
Wrapper context.
('zu', 'cc')
(1999, 1, 1)
{'school': 'zucc'}
函数被多个装饰器所装饰
一个函数在使用时,通过一个装饰器来拓展,可用多个装饰器来装饰
#装饰器1
def setFunc1(func):
def wrapper1(*args, **kwargs):
print('Wrapper Context 1 Start'.center(40, '*'))
func(*args, **kwargs)
print('Wrapper Context 1 end'.center(40, '*'))
return wrapper1
#装饰器2
def setFunc2(func):
def wrapper2(*args, **kwargs):
print('Wrapper Context 2 Start'.center(40, '*'))
func(*args, **kwargs)
print('Wrapper Context 2 end'.center(40, '*'))
return wrapper2
@setFunc1
@setFunc2
def show(*args, **kwargs):
print('show run.'.center(40, '*'))
show() # F(g(f)) 嵌套先装饰最近的 2 再装饰1
********Wrapper Context 1 Start*********
********Wrapper Context 2 Start*********
***************show run.****************
*********Wrapper Context 2 end**********
*********Wrapper Context 1 end**********
总结:
-
函数可以像普通变量一样,作为函数的参数或者返回值进行传递。
-
函数的内部可以定义另外一个函数。目的,隐藏函数功能的实现。
-
闭包实际上也是函数定义的一种形式。
-
闭包定义的规则,再外部函数内定义一个内部函数,内部函数使用外部函数的变量,并返回内部函数的引用。
-
Python中,装饰器就是用闭包来实现的。
-
装饰器的作用,不改变现有函数的基础上,为函数增加功能。
-
装饰器的使用,通过
@装饰器函数名
的形式来给已有函数进行装饰,添加功能。 -
装饰器四种形式,根据参数的不同以及返回值的不同。
-
万能装饰器,通过可变参数(*args/**kwargs)来实现。
-
一个装饰器可以为多个函数提供装饰功能。
-
一个函数也可以被多个装饰器所装饰。
-
通过类实现装饰器,重写
__init__
和__call__
函数。 -
类装饰器再装饰函数后,原来的引用不再是函数,儿视装饰类的对象。