目錄
- 一、閉包
- 二、一個簡單的例子
- 三、裝飾器
- 3.1 簡單裝飾器
- 3.1.1 使用裝飾器的語法糖
- 3.1.2 裝飾器的執行時機
- 3.2 通用裝飾器
- 3.2.1 裝飾帶有參數的函數
- 3.2.2. 裝飾帶有返回值的函數:
- 3.2.3 實現通用裝飾器
- 3.3 多個裝飾器的使用
- 3.4 帶有參數的裝飾器
- 3.5 類裝飾器
一、閉包
閉包的形成條件:
1.函數嵌套。
2.內部函數使用了外部函數的變量或者參數。
3.外部函數返回了使用外 部變量的內部函數。
二、一個簡單的例子
def func_out(num1):
def inner(num2):
res = num1 + num2
print(res)
return inner
# a = func_out(10)(10)
a = func_out(10)
a(10)
閉包修改外部函數的變量:
在閉包內修改外部函數的變量需要使用nonlocal關鍵字
def func_out():
# 外部函數的變量
num1 = 10
def func_inner():
# 在閉包內修改外部函數的變量
nonlocal num1
num1 = 20
res = num1 +20
print(res)
print("修改前的變量", num1)
func_inner()
print("修改后的變量", num1)
return func_inner
new_func = func_out()
new_func()
三、裝飾器
3.1 簡單裝飾器
裝飾器就是給已有函數增加額外功能的函數,它本質上就是一個閉包函數,也就是說也是一個函數嵌套。裝飾器的功能特點:
1.不修改已有函數的源代碼
2.不修改已有函數的調用方式
3.給已有函數增加額外的功能
用戶在發表評論的時候需要驗證用戶是否登錄,我們首先會想到去修改原來的函數,在函數里面添加一些功能,但是在現在這分工合作的時代,這樣的修改很容易出現修改了祖傳的代碼后,函數出現問題,也影響代碼的高效復用。為了能夠不重新修改原來的評論的代碼,實現高水平的代碼復用。
原本的函數及其調用:
def comment():
print("執行祖傳代碼.....")
print("發表評論")
# 調用評論功能
comment()
自己手寫一個實現裝飾器功能的函數實現登錄驗證:
def decorator(func):
def inner():
print('正在驗證登錄者身份...\n驗證成功')
func()
return inner
def comment():
print("執行祖傳代碼.....")
print("發表評論")
# 調用評論功能
comment = decorator(comment)
comment()
輸入結果:
正在驗證登錄者身份…
驗證成功
執行祖傳代碼…
發表評論
3.1.1 使用裝飾器的語法糖
裝飾器的語法糖寫法:@裝飾器名稱
如例子可以改寫為:
def decorator(func):
def inner():
print('正在驗證登錄者身份...\n驗證成功')
func()
return inner
@decorator
def comment():
print("執行祖傳代碼.....")
print("發表評論")
# 調用函數
comment()
運行結果:
正在驗證登錄者身份…
驗證成功
執行祖傳代碼…
發表評論
3.1.2 裝飾器的執行時機
先說結論:在使用裝飾器語法糖時,會先將該裝飾器函數執行一遍。
def decorator(func):
# 測試裝飾器的執行時機
print('--remark1----')
def inner():
print('正在驗證登錄者身份...\n驗證成功')
func()
print('----remark2---')
return inner
@decorator
def comment():
print("執行祖傳代碼.....")
print("發表評論")
輸出結果:
–remark1----
----remark2—
3.2 通用裝飾器
裝飾的函數可能有參數傳遞,或者有返回值,上面寫的例子中,如果依然用上面的方法及逆行裝飾器的裝飾將會出現問題,那是否有一個通用的裝飾器能夠裝飾任意函數呢?
3.2.1 裝飾帶有參數的函數
def logging(fn):
def inner(num1,num2):
print('執行了一次計算')
fn(num1,num2)
return inner
# 使用裝飾器裝飾函數
@logging
def sum_num(a,b):
result = a + b
print(result)
sum_num(1,2)
3.2.2. 裝飾帶有返回值的函數:
def logging(fn):
def inner(num1,num2):
print('執行了一次計算')
result = fn(num1,num2)
return result
return inner
# 使用裝飾器裝飾函數
@logging
def sum_num(a,b):
result = a + b
return result
print(sum_num(1,2))
3.2.3 實現通用裝飾器
*args
: 用于接收元組參數,可傳可不傳
**kwargs
: 用于接收字典類型參數,可傳可不傳
def logging(fn):
def inner(*args, **kwargs):
result = fn(*args, **kwargs)
return result
return inner
@logging
def sum_num(a,b):
result = a + b
return result
3.3 多個裝飾器的使用
多個裝飾器的過程:由內到外的裝飾過程,先執行內部裝飾器,再執行外部裝飾器。
原理剖析:content = make_div(make_p(content))
分步拆解:content = make_p(content), 內部裝飾器完成content=make_p.inner, content = make_div(make_p.inner)
def make_div(func):
print("make_div裝飾器執行了")
def inner():
# 在內部函數對已有函數進行裝飾
result = "div>" + func() +"/div>"
return result
return inner
def make_p(func):
print("make_p裝飾器執行了")
def inner():
# 在內部函數對已有函數進行裝飾
result = "p>" + func() +"/p>"
return result
return inner
@make_div
@make_p
def content():
return "人生苦短,我用Python"
輸出:
make_p裝飾器執行了
make_div裝飾器執行了
div>p>人生苦短,我用Python/p>/div>
3.4 帶有參數的裝飾器
帶有參數的裝飾器時機上就是定義了一個函數,讓函數接收參數,再函數內部返回該裝飾器。
如定義一個能夠判斷加減的裝飾器:
def return_decorator(flag):
def decorator(func):
def inner(a,b):
if flag == '+':
print("正在進行加法運算")
elif flag == '-':
print("正在進行減法運算")
func(a,b)
return inner
return decorator
@return_decorator('+')
def add_num(a,b):
print(a+b)
add_num(1,5)
3.5 類裝飾器
使用類裝飾已有函數。
class MyDecorator(object):
def __init__(self,func):
self.__func = func
# 實現__call__方法,讓對象變成可調用的對象,
# 可調用的對象能夠像函數一樣被使用。
def __call__(self,*args,**kwargs):
# 對已有參數進行封裝
print('--正在進行裝飾-----')
self.__func()
@MyDecorator
def show():
print("hello")
# 指向MyDecorator類創建實例對象--> show()==> 對象()
show()
輸出:
–正在進行裝飾-----
hello
到此這篇關于python高級語法之閉包和裝飾器詳解的文章就介紹到這了,更多相關python閉包和裝飾器內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- python閉包和裝飾器你了解嗎
- Python 中閉包與裝飾器案例詳解
- Python必備基礎之閉包和裝飾器知識總結
- Python 中的函數裝飾器和閉包詳解
- python閉包的實例詳解