目錄
入門使用
我們先從最基本的開始,創建一個函數嵌套函數試試行不行,調用輸出。成了!那我們再試試調用嵌套函數看看。
def First():
print("這是主函數!")
def First_1():
print('這是主函數嵌套的函數 First_1 ')
#我們在主函數裏面調用嵌套函數
First_1()
First()
這是主函數! 這是主函數嵌套的函數 First_1
#然後我們在外面調用嵌套函數試試,發現報錯了: 說明這個函數沒有定義
First_1()
>>>
name 'First_1' is not defined
發現失敗了,到這裏我們可以發現在函數裏面嵌套的函數其實跟局部變量差不多,作用域只在它所在函數裏面,那我們是不是也可以將函數作爲參數進行傳遞給函數呢?我們來進行以下測試。
#創建一個函數,參數爲func,也就是函數
def Second(func):
print("下面的輸出是調用func")
func()
#創建一個作爲函數參數
def Cxk():
print('這是一個函數參數')
#我們來調用一下,看會發生什麼
Second(Cxk)
哎,不出所料,被調用的函數成功進行了輸出
>>>下面的輸出是調用func
這是一個函數參數
函數是變量,那也就具備了一些變量的特性咯,比如返回變量?來試試!
#依舊是創建一個函數,參數爲func,也就是函數
def Third(func):
print("下面返回func")
return func
#創建一個作爲函數參數,並讓它返回一串字符
def Cxk():
return '這是一個函數參數'
我們來調用一下,接收返回看會發生什麼
a=Third(Cxk)
先看看接收到的返回a是什麼類型
print(type(a),"這是Third函數調用Cxk函數進行的返回%s"%a)
這是輸出>>>
下面返回func <class 'function'> 這是Third函數調用Cxk函數進行的返回<function Cxk at 0x000001445E5F1EA0>
依舊不出所料,能跟變量一樣進行返回
>>>
下面返回func
<class 'str'> 這是Third函數調用Cxk函數進行的返回這是一個函數參數<function Cxk at 0x000001445E5F1EA0>
其實由此我們就已經創建了一個裝飾器,下面我們來看看真正的裝飾器是怎麼樣的。我們用一個例子來看看。
import time
def demo(fun):
"""
計算函數運行時間的裝飾器
fun:函數
"""
def wrapper():
print('函數開始運行')
star_time=time.time() # 記錄函數開始運行的時間
fun() # 運行的函數
end_time=time.time() # 記錄函數運行結束後的時間
print('運行時間:%.8f' %(end_time-star_time)) # 打印出函數運行的時間
return wrapper
#我們創建一個生成列表並求和的函數
@demo
def new_list():
print(sum([x for x in range(0,101)]))
#我們直接運行這函數看看吧
new_list()
>>>
函數開始運行
5050
運行時間:0.00099754
不可思議!
我們不僅調用了new_list(),還調用demo()
觀察以上例子,我們能發現什麼?
一開始:以上我們對於函數的調用都是在調用最新的函數(比如:First,Second,Third),然後該函數再調用功能函數(比如:First_1,Cxk)
現在呢:我們直接調用功能函數,然後再調用最新的函數實現附加的功能
爲什麼我要叫最新的函數呢,因爲這就是裝飾器的一個作用,
當我們功能函數已經運行很久了,現在又想附加功能,我們只能去更改原函數,但有時候牽一髮而動全身,
所以裝飾器就出來了,我們創建最新的函數嵌套以前的功能函數豈不是直接實現了附加功能
那爲什麼會這樣呢?
請看這個小東西@demo
@這叫修飾符,@ 符號就是裝飾器的語法糖,它放在函數開始定義的地方,這樣就可以省略最後一步再次賦值的操作。
這是網上的:
作用是爲現有函數增加額外的功能,常用於插入日誌、性能測試、事務處理等等。
創建函數修飾符的規則:
(1)修飾符是一個函數
(2)修飾符取被修飾函數爲參數
(3)修飾符返回一個新函數
(4)修飾符維護被維護函數的簽名
看得懂看不懂都沒關係,只要記得這幾個規則就行了,通俗的來講,裝飾裝飾,意思上理解就是生活中小揹包的一個飾品,讓我們的書包看起來更美觀,而飾品買包的時候是沒有的,這是我們自己買來裝上去的,所以說裝飾器就是爲函數實現不同的功能而創造的。這裏我們的讓包看起來更美觀就是我們要實現的功能。
進階使用
好了,現在我們已經基本瞭解什麼叫裝飾器了,那它有什麼用呢?或者它用在什麼地方?
其實上邊也已經說了一些:插入日誌、性能測試、事務處理等等。
帶參數的裝飾器
def demo(func):
new_number=3
def wrapper(*args,**kwargs): #裝飾後的方法
print("函數開始運行")
sum_result=func(*args,**kwargs)
sum_result+=new_number
print('函數結束')
return sum_result
return wrapper
@demo
def add(a,b):
return a+b
add(1,2)
>>>
函數開始運行
函數結束
6
至此我們可以看見原函數只能進行兩個數加減,我們添加一個功能,經過修飾器後我們給它添加了第三個數。那我們怎麼不再函數內定義數,而直接給裝飾器的語法糖上附帶第三個數呢?源代碼修改成以下
def demo(new_number):
def add_number(func):
def wrapper(*args,**kwargs): #裝飾後的方法
print("函數開始運行")
sum_result=func(*args,**kwargs)
sum_result+=new_number
print('函數結束')
return sum_result
return wrapper
return add_number
#接收參數
@demo(new_number=3)
def add(a,b):
return a+b
add(1,2)
>>>
函數開始運行
函數結束
6