引言:
函數和裝飾器好比程序界的加工廠:
1、函數一般可用來加工一種或者多種數據類型的數據:字符串、數字、列表、字典等
舉一個簡單例子:已知半徑求面積
def s(r):
s = 3.14 * r * r
return s
調用s函數:輸入4,輸出半徑為4的圓的面積。a相當于面積的容器
a = s(4)
print(a)
2、裝飾器是用來裝飾函數的函數。其需要輸入的原材料為某個函數
以下是裝飾器的固定格式:
1 def timer(func):
2 def inner(*args,**kwargs):
3 '''執行函數之前要做的'''
4 re = func(*args,**kwargs)
5 '''執行函數之后要做的'''
6 return re
7 return inner
timer函數是一個進化函數的函數:裝飾器
timer是用來加工函數的,即產品應該也應該是函數(進化版)。
def timer(func):
#
#func的進化過程
#
return inner # 強化變身版func
上面的代碼就比較容易理解了,就是定義一個函數去強化函數,得到一個強化func
接下來,我們就深入研究func的強化過程:
1、你return了一個inner函數,他不是憑空產生的,就是石猴還不遠萬里去學藝,并取了了名字叫孫悟空呢。
所以一開始你要:
def inner(*args,**kwargs): # inner 今天成立了
我們知道inner是為了強化加工廠func的,所以inner需要的原材料必須是和func一樣的。啟動萬能可變參數(args,*kwargs)
def inner(*args,**kwargs):
'''執行函數之前要做的''' # 強化1
re = func(*args,**kwargs) # 這個是原函數的核心部件,你就不要隨便動他了。。。否則,你為啥不自己寫一個程序。。。
'''執行函數之后要做的''' #強化2
return re
我們再講一下為啥要要有 re 這個東西,還要return
因為這就是func原工廠生產的東西啊。。。沒有return 你就丟了啊
到了最后變身的 時候了。。。
hahaha之前是一個小小加工廠,注冊資金只有10w
后來王思聰老公投資了1億,hahaha立馬走上人生巔峰
inner 是哈哈哈被timer(王思聰)強化后的hahaha
這時候工商局找來了。。。指著inner說,你不就是原來的hahaha么,必須在我這更改相關信息,但是名字就不能改了
認證:hahaha = timer(hahaha) # 注冊資金1億
后來工商局發現經常性工廠升級,所以后來就直接在營業執照上蓋了個戳
@timer
講了這么多,就是為了加深大家的理解,其實記住下面的就好了
def wrapper(func):
def inner(*args,**kwargs):#定義函數的時候——*參數的聚合
ret = func(*args,**kwargs) #調用函數的時候——*參數的打散
#func是被裝飾的函數,ret是被裝飾函數的返回值
return ret #把被裝飾的函數的返回值返回給調用者
return inner
帶參數的裝飾器
假如你有成千上萬個函數使用了一個裝飾器,現在你想把這些裝飾器都取消掉,你要怎么做?
def outer(flag):
def timer(func):
def inner(*args,**kwargs):
if flag:
print('''執行函數之前要做的''')
re = func(*args,**kwargs)
if flag:
print('''執行函數之后要做的''')
return re
return inner
return timer
@outer(False)
def func():
print(111)
func()
多個裝飾器裝飾同一個函數
def wrapper1(func):
def inner():
print('wrapper1 ,before func')
func()
print('wrapper1 ,after func')
return inner
def wrapper2(func):
def inner():
print('wrapper2 ,before func')
func()
print('wrapper2 ,after func')
return inner
@wrapper2
@wrapper1
def f():
print('in f')
f()
附加:關于可變參數的應用
#動態參數
def ccc(*args):#1,2,3,4,5
print(args)
ccc(1,2,3,4,5)#按位置傳參數
t = (1,2,3,4,5)
ccc(t) ((1, 2, 3, 4, 5),)
ccc(*t) (1, 2, 3, 4, 5)
def ddd(**kwargs):
print(kwargs)
# ddd(k = 'a',j = 'b')#按關鍵字傳參數
def eee(*args,**kwargs):
print(args,kwargs)
# eee(12,123) #先按位置傳參,再按關鍵字傳參
def ccc(*args):
print('ccc:',args) #(1,2,3,4,5)
def inner(a,b,c,d,e):
print('inner',a,b,c,d,e)
inner(*args) #*(1,2,3,4,5) 打散
def inner(a,b,c,d,e):
print('inner',a,b,c,d,e)
# ccc(1,2,3,4,5)
# inner(1,2,3,4,5)