Python中函數(shù)的閉包和裝飾器示例詳解
1. python的內(nèi)部函數(shù)示例
# 定義一個外部函數(shù)
def func_out(num1):
# 定義一個內(nèi)部函數(shù)
def func_inner(num2):
# 內(nèi)部函數(shù)使用了外部函數(shù)的變量(num1)
result = num1 + num2
print("結(jié)果是:", result)
# 外部函數(shù)返回了內(nèi)部函數(shù),這里返回的內(nèi)部函數(shù)就是閉包
return func_inner
# 創(chuàng)建閉包實(shí)例,返回內(nèi)部函數(shù)
# 此時(shí)的f是內(nèi)部函數(shù)
f = func_out(100)
# 執(zhí)行閉包
f(2)
f(3)
"""
f接收到func_out的返回值
f = func_inner
f() = func_inner()
"""示例2:
def config_name(name):
def say_hello(info):
print(f"{name}: {info}")
return say_hello
if __name__ == '__main__':
# 創(chuàng)建閉包實(shí)例
tom = config_name("tom")
tom("What did you have for lunch ?")
jarry = config_name("jarry")
jarry("I had vegetables and beef.")
"""
tom: What did you have for lunch ?
jarry: I had vegetables and beef.
"""調(diào)用閉包相當(dāng)于調(diào)用內(nèi)部函數(shù)
閉包的構(gòu)成條件
1. 在函數(shù)嵌套的前提下
2. 內(nèi)部函數(shù)使用了外部函數(shù)的變量(還包括外部函數(shù)的參數(shù))
3. 外部函數(shù)返回了內(nèi)部函數(shù)結(jié)論:閉包可以對外部函數(shù)的變量進(jìn)行保存
2. 閉包內(nèi)修改外部變量
def func_out(num1):
def func_inner(num2):
# 此時(shí)的num1屬于內(nèi)部函數(shù),不是外部函數(shù)的num1
num1 = num2 + 100
print("改前:num1 =",num1)
# 調(diào)用內(nèi)部函數(shù)修改num1的值
func_inner(200) # 調(diào)用方法改變num1的值
print("改后:num1 =",num1)
return func_inner
# 實(shí)例化閉包
f = func_out(10)
"""
改前:num1 = 10
改后:num1 = 10
"""def func_out(num1):
def func_inner(num2):
# 此時(shí)的num1是外部函數(shù)變量
nonlocal num1
num1 = num2 + 100
print("改前:num1 =",num1)
# 調(diào)用內(nèi)部函數(shù)修改num1的值
func_inner(200) # 調(diào)用方法改變num1的值
print("改后:num1 =",num1)
return func_inner
# 實(shí)例化閉包
f = func_out(10)
# f(10) --> 這是調(diào)用閉包(內(nèi)部函數(shù)),這里沒有調(diào)用閉包,只是創(chuàng)建了閉包
"""
改前:num1 = 10
改后:num1 = 300
"""修改閉包使用的外部函數(shù)變量使用nonlocal關(guān)鍵字修飾
3. 裝飾器:在不改變原有函數(shù)的源代碼的情況下,給函數(shù)添加功能
1.不修改原有函數(shù)的源代碼
2. 給已有的函數(shù)添加額外的功能符合開發(fā)中的封閉開放原則
# 1. 定義一個裝飾器(一個閉包, 一個內(nèi)部函數(shù))
def check(fn):
# fn是comment函數(shù)
def inner():
print("請先登錄")
fn()
return inner
# 2. 需要被裝飾的函數(shù)
def comment():
print("發(fā)表評論")
# 3. 使用裝飾器裝飾函數(shù)(增加一個登錄功能)
# 左側(cè)的comment函數(shù)已經(jīng)變成了inner()函數(shù)
comment = check(comment)
comment()
"""
請先登錄
發(fā)表評論
"""裝飾器就是把一個函數(shù)當(dāng)作參數(shù)傳遞給閉包中的外部函數(shù),同時(shí)在內(nèi)部函數(shù)中使用這個函數(shù),并給它添加新的功能
def check(fn):
def inner():
print("請先登錄")
fn()
return inner
# 解釋器遇到@check,會執(zhí)行comment = check(comment)
@check
def comment():
print("發(fā)表評論")
comment()
"""
請先登錄
發(fā)表評論
"""4.修飾帶參數(shù)的函數(shù)
"""裝飾帶參數(shù)的函數(shù)"""
def loggin(fn):
def inner(a,b):
print("請先登錄")
fn(a,b)
return inner
def sum_num(a,b):
result = a+b
print(result)
# sum_num = inner
sum_num = loggin(sum_num)
sum_num(1,2)
"""
請先登錄
3
""""""裝飾帶參數(shù)的函數(shù)"""
def loggin(fn):
def inner(a,b):
print("請先登錄")
fn(a,b)
return inner
# sum_num = inner, sum_sum = loggin(sum_num)
@loggin
def sum_num(a,b):
result = a + b
print(result)
sum_num(1,2)
"""
請先登錄
3
"""5. 裝飾帶有返回值的函數(shù)
"""裝飾帶返回值的函數(shù)"""
def loggin(fn):
def inner(a,b):
print("請先登錄")
return fn(a,b)
return inner
@loggin
def sum_num(a,b):
result = a+b
return result
ans = sum_num(1,2)
print("ans = ",ans)
"""
請先登錄
ans = 3
"""6. 修飾不定長參數(shù)的函數(shù)
def loggin(fn):
def inner(*args):
print("請先登錄")
return fn(*args)
return inner
@loggin
def sum_args(*args):
ans = sum(args)
return ans
ans = sum_args(1,2,3,4,5)
print("ans = ",ans)
"""
請先登錄
ans = 15
"""7. 多個裝飾器的使用
def check1(fn):
def inner1():
print("登錄驗(yàn)證1")
fn()
return inner1
def check2(fn):
def inner2():
print("登錄驗(yàn)證2")
fn()
return inner2
@check2
@check1
def comment():
print("發(fā)表評論")
comment()
"""
登錄驗(yàn)證2
登錄驗(yàn)證1
發(fā)表評論
"""8. 帶有參數(shù)的裝飾器
"""
帶參數(shù)的裝飾器,正確案例
"""
def loggin(flag):
def decorator(fn):
def inner(num1, num2):
# 判斷流程
if flag == "+":
print("--正在努力加法計(jì)算--")
elif flag == "-":
print("--正在努力減法計(jì)算--")
ant = fn (num1,num2)
return ant
return inner
return decorator
# 被帶有參數(shù)的裝飾器飾的函數(shù)
@loggin("+") # 1. loggin("+") 2. @decorator起到裝飾器的功能了
def sum_num(a, b):
res = a + b
return res
result = sum_num(1,3)
print("result = ",result)帶參數(shù)的裝飾器
1. 裝飾器的外部函數(shù)只接受一個參數(shù) -- 被裝飾的函數(shù)
2. 需要給裝飾器參數(shù)需要在裝飾器外部再增加一個函數(shù)
9. call方法
class Check(object):
def __call__(self,*args,**kwargs):
print("請先登錄")
c1 = Check()
c1()
"""請先登錄"""10. 類裝飾器
class Check(object):
def __init__(self,fn):
self._fn = fn
def __call__(self,*args,**kwargs):
print("請先登錄")
self._fn()
@Check # comment = Check(comment)
def comment():
print("發(fā)表評論")
comment()
"""
請先登錄
發(fā)表評論
"""11. property 裝飾器方式
class Person(object):
def __init__(self) -> None:
self.__age = 0
@property
def age(self):
return self.__age
@age.setter
def age(self, new_age):
self.__age = new_age
p = Person()
print(p.age)
p.age = 100
print(p.age)12. property類屬性方式
class Person(object) :
def __init__(self) -> None:
self.__age = 0
def get_age(self):
return self.__age
def set_age(self, new_age):
if new_age >= 150:
print("年齡錯誤")
else:
self.__age = new_age
age = property(get_age, set_age)
p = Person()
print(p.age)
p.age = 60
print( p.age )總結(jié)
到此這篇關(guān)于Python中函數(shù)的閉包和裝飾器的文章就介紹到這了,更多相關(guān)Python函數(shù)的閉包和裝飾器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python 3.8新特征之a(chǎn)syncio REPL
我最近都在寫一些Python 3.8的新功能介紹的文章,在自己的項(xiàng)目中也在提前體驗(yàn)新的Python版本。這篇文章主要介紹了Python 3.8新特征之a(chǎn)syncio REPL,需要的朋友可以參考下2019-05-05
簡單實(shí)現(xiàn)python收發(fā)郵件功能
這篇文章主要教大家如何簡單實(shí)現(xiàn)python收發(fā)郵件功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
Pycharm2020.1安裝無法啟動問題即設(shè)置中文插件的方法
這篇文章主要介紹了Pycharm2020.1安裝無法啟動問題即設(shè)置中文插件的操作方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2020-08-08
python 已知一個字符,在一個list中找出近似值或相似值實(shí)現(xiàn)模糊匹配
今天小編就為大家分享一篇python 已知一個字符,在一個list中找出近似值或相似值實(shí)現(xiàn)模糊匹配,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02
opencv矩形輪廓頂點(diǎn)的具體位置確定的兩種實(shí)現(xiàn)方法
本文主要介紹了opencv矩形輪廓頂點(diǎn)的具體位置確定,通過線性規(guī)劃和最小面積矩兩種方法定位紙張四個頂點(diǎn),具有一定的參考價(jià)值,感興趣的可以了解一下2025-07-07

