1. 程式人生 > >python裝飾器:有引數的裝飾器、不定長引數的裝飾器、裝飾有返回值的函式、通用的裝飾器

python裝飾器:有引數的裝飾器、不定長引數的裝飾器、裝飾有返回值的函式、通用的裝飾器

將一個函式作為另一個函式的引數,返回值賦給這個函式

def func(funcname):
	print("----fun 1---")
	def fun_in():
		print("----fun_in----1")
		funcname()
		print("----fun_in----2")
	print("----func2-----")
	return fun_in
def test():
	print("----test----")
 
test=func(test)
test()
#上面的執行結果:
'''執行結果
----fun 1---
----func2-----
----fun_in----1
----test----
----fun_in----2
'''

上面是之前學過的函式的使用,這裡我們採取裝飾器的方式達到相同的效果

#前面對test的使用用到了test=func(test),可以使用裝飾器來達到相同的效果
@func
def test2():
	print('----test2----')
 
test2()
'''執行結果
----fun 1---
----func2-----
----fun_in----1
----test2----
----fun_in----2
'''

考慮多種情況的裝飾器:

1.有引數的裝飾器

def funcProperty(funcname):
	print("----funPro 1---")
	def fun_in(a,b):#test(2,0)呼叫的是這個函式,需要有兩個引數
		print("----fun_in----1")
		funcname(a,b)#這裡的test(2,0)作為引數傳遞進來,需要有兩個引數
		print("----fun_in----2")
	print("----funcPro2-----")
	return fun_in
@funcProperty
def test(a,b):
	print("----the property is %d,%d----"%(a,b))
 
test(2,0)
'''執行結果
----funPro 1---
----funcPro2-----
----fun_in----1
----the property is 2,0----
----fun_in----2
'''

 2.不定長引數

#對於不定長引數的函式的處理
def funcPro(funcName):
	print("---不定長引數的傳遞---")
	def func_in(*args,**kwargs):#前面傳遞的是元組,後面是字典
		print("----args,kwargs---")
		funcName(*args,**kwargs)
		print("-----end args ,kwargs----")
	print("---不定長引數傳遞結束--")
	return func_in
@funcPro
def testThree(a,b,c):
	print("----test  a=%d,b=%d,c=%d----"%(a,b,c))
 
testThree(1,2,3) #這裡引數傳遞幾個值,都可以,跟test對應起來就可以
'''執行結果
----funPro 1---
----funcPro2-----
---不定長引數的傳遞---
---不定長引數傳遞結束--
----args,kwargs---
----test  a=1,b=2,c=3----
-----end args ,kwargs----
'''

 3.對帶有返回值的函式進行裝飾

#再次分析:上面進行裝飾的時候,已經把testThree作為 引數傳遞過去,下面testThree(1,2,3)執行的時候,就是呼叫func_in
#testThree(1,2,3)指向的就是func_in,func_in中的funcName就呼叫了testThree(a,b,c)的內容
 
#使用裝飾器對帶有返回值的函式進行裝飾
#
def funcReturn(functionName):
	print("---有返回值的函式---")
	def func_in():
		print("--先進行裝飾,將有返回值的函式作為引數傳遞進來")
		res=functionName()
		print("--呼叫有返回值的函式後--")
		return res
	print("---有返回值的函式裝飾結束---")
	return func_in
@funcReturn
def testRe():
	print("---這個函式有返回值")
	return "測試有返回結果"
 
ret=testRe()
print("the end value is %s"%ret)
'''執行結果
---有返回值的函式---
---有返回值的函式裝飾結束---
--先進行裝飾,將有返回值的函式作為引數傳遞進來
---這個函式有返回值
--呼叫有返回值的函式後--
the end value is 測試有返回結果
'''

根據前面的幾種情況我們可以考慮設計一個通用的裝飾器:

#一個通用的裝飾器
def funcAll(funcName):
	def func_in(*args,**kwargs):
		ret=funcName(*args,**kwargs)
		return ret
	return func_in
#這個通用的裝飾器,有無返回值都可以,沒有返回值的話,ret=None,引數的話採用不定長引數

我們可以根據裝飾器的函式的引數不同,進行不同的操作

#帶有引數的裝飾器
def func_arg(arg):
	def funcAll(funcName):
		def func_in(*args,**kwargs):
			if arg=="2":#根據裝飾的引數不同,可以進行不同的處理
				ret=funcName(*args,**kwargs)
				ret=funcName(*args,**kwargs)
			else:
				ret=funcName(*args,**kwargs)
			print("arg is %s"%arg)
			return ret
		return func_in
	return funcAll
#執行分析:
#1 先執行func_arg("hello")函式,這個函式return的結果是func這個函式的引用
#2 @func_arg("hello")----->@funcAll
#3 使用@func對testArg()進行裝飾
 
 
@func_arg("hello")
def testArg():
	print("---帶有引數的裝飾器---")
 
@func_arg("2")
def testArg2():
	print("---帶有引數的裝飾器---")
testArg()
testArg2()
'''執行結果
---帶有引數的裝飾器---
arg is hello
---帶有引數的裝飾器---
---帶有引數的裝飾器---
arg is 2
'''
#帶有引數的裝飾器,在執行中可以根據引數進行不同執行