python函數(shù)閉包概念
一、函數(shù)
函數(shù)是實現(xiàn)特定功能的代碼段的封裝,在需要時可以多次調(diào)用函數(shù)來實現(xiàn)該功能。
Python如下定義一個函數(shù),我們可以通過任何變量來將此函數(shù)進行賦值操作,如下:
def greet(): return "Hello!" # 將方法賦給變量(無括號,得到方法對象) greet_func = greet # 調(diào)用存儲在變量中的方法 print(greet_func()) print(type(greet_func)) # 輸出 greet_func 的類型,由于 greet_func 指向的是 greet 函數(shù)對象,所以輸出結(jié)果為 <class 'function'> print(type(greet_func())) # 先調(diào)用 greet_func 所指向的函數(shù),得到返回值 "Hello!",然后輸出該返回值的類型,結(jié)果為 <class 'str'>。 # 有括號,直接調(diào)用方法并將結(jié)果賦給變量 greet_result = greet() print(greet_result) print(type(greet_result)) # 輸出 greet_result 的類型,由于它存儲的是字符串,所以輸出結(jié)果為 <class 'str'> print(type(greet_result())) # 報錯greet_result 存儲的是字符串 "Hello!",而不是函數(shù)對象,所以不能像調(diào)用函數(shù)一樣在它后面加上括號 ()
在 Python 中,函數(shù)是一等公民,這意味著函數(shù)可以像其他對象(如整數(shù)、字符串等)一樣被賦值給變量。這里將 greet
函數(shù)對象賦值給了變量 greet_func
。此時 greet_func
實際上指向的是 greet
函數(shù)本身,而不是函數(shù)的返回值;而 greet_result = greet()
是先調(diào)用 greet
方法,然后把返回值賦給 greet_result
變量。
二、閉包
2.1 概念
在 Python 中,閉包(Closure)是一種特殊的函數(shù),它由一個函數(shù)和該函數(shù)所引用的外部作用域中的變量組成。即使外部函數(shù)已經(jīng)執(zhí)行完畢,其局部變量的生命周期也會因閉包的存在而得以延長,閉包可以繼續(xù)訪問這些變量。
簡單來說,閉包允許函數(shù)訪問并操作其定義所在的外部作用域中的變量,即使該外部作用域已經(jīng)結(jié)束。
構(gòu)成閉包需要滿足以下三個條件:
- 存在一個嵌套函數(shù),即在一個函數(shù)內(nèi)部定義另一個函數(shù)。
- 嵌套函數(shù)引用了外部函數(shù)的局部變量。
- 外部函數(shù)返回嵌套函數(shù)。
2.2 閉包的應(yīng)用場景
- 數(shù)據(jù)封裝和隱藏:可以將數(shù)據(jù)隱藏在閉包內(nèi)部,只通過閉包提供的接口來訪問和修改數(shù)據(jù)。
- 實現(xiàn)回調(diào)函數(shù):在事件驅(qū)動編程中,閉包可以作為回調(diào)函數(shù),保存一些上下文信息。
- 實現(xiàn)裝飾器:裝飾器是閉包的一種常見應(yīng)用,用于在不修改原函數(shù)代碼的情況下,為函數(shù)添加額外的功能。
2.3 代碼實例
實例 1:簡單計數(shù)器閉包
def outer_function(): # 外部函數(shù)的局部變量 count = 0 def inner_function(): # 聲明count為外部函數(shù)的局部變量, 以便可以修改它 nonlocal count count = count + 1 return count return inner_function # 創(chuàng)建閉包實例 counter = outer_function() # 多次調(diào)用閉包 print(counter()) # 輸出: 1 print(counter()) # 輸出: 2 print(counter()) # 輸出: 3
代碼解釋:
outer_function
是外部函數(shù),它定義了局部變量count
并初始化為 0。inner_function
是嵌套在outer_function
內(nèi)部的函數(shù),它引用了外部函數(shù)的count
變量,并對其進行加 1 操作。nonlocal
關(guān)鍵字用于告訴 Python,count
變量不是當(dāng)前inner_function
的局部變量,而是外部函數(shù)的局部變量,這樣才能在內(nèi)部函數(shù)中修改它。outer_function
返回了inner_function
,形成了閉包。當(dāng)調(diào)用outer_function()
時,會返回inner_function
的引用并賦值給counter
。每次調(diào)用counter()
時,count
變量的值都會在之前的基礎(chǔ)上增加 1,說明count
變量的狀態(tài)被閉包保存下來了。
實例 2:帶參數(shù)的閉包
def multiplier(factor): print("++++++", factor) def multiply_by_factor(number): print("++++++", number) return number * factor return multiply_by_factor # 創(chuàng)建一個乘以 3 的閉包 triple = multiplier(3) # 調(diào)用 __closure__ 內(nèi)置方法可以查看到兩個內(nèi)存地址,結(jié)果返回cell就是閉包,None 則不是閉包,可以看出來其實這是一個元組類型,使用[0].cell_contents可以得到閉合數(shù)值,也就閉包所需要的環(huán)境變量。 print(triple.__closure__) # 閉包所需要的環(huán)境變量 print(triple.__closure__[0].cell_contents) print(triple.__class__) print(triple(5))
代碼解釋:
multiplier
是外部函數(shù),它接受一個參數(shù)factor
。multiply_by_factor
是嵌套函數(shù),它接受一個參數(shù)number
,并返回number
乘以factor
的結(jié)果。multiplier
返回multiply_by_factor
,形成閉包。調(diào)用multiplier(2)
會返回一個閉包,該閉包會將傳入的數(shù)字乘以 2,將其賦值給double
。同理,multiplier(3)
返回的閉包會將傳入的數(shù)字乘以 3,賦值給triple
。
運行結(jié)果:
實例 3:閉包用于數(shù)據(jù)封裝和隱藏
def account(initial_balance): balance = initial_balance def deposit(amount): nonlocal balance balance = balance + amount return balance def withdraw(amount): nonlocal balance if amount <= balance: balance = balance - amount return balance else: print("余額不足") return balance def get_balance(): return balance return deposit, withdraw, get_balance # 創(chuàng)建賬戶閉包 deposited, withdrawed, get_balanceed = account(1000) # 存款操作 print(deposited(500)) # 輸出: 1500 # 取款操作 print(withdrawed(200)) # 輸出: 1300 # 查詢余額 print(get_balanceed()) # 輸出: 1300
代碼解釋:
account
是外部函數(shù),它接受一個初始余額initial_balance
并將其賦值給局部變量balance
。deposit
、withdraw
和get_balance
是嵌套函數(shù), 它們 都引用了外 部函數(shù)balance
變量。deposit
函數(shù)用于存款,withdraw
函數(shù)用于取款,get_balance
函數(shù)用于查詢余額。account
函數(shù)返回這三個嵌套函數(shù),形成閉包。通過調(diào)用account(1000)
創(chuàng)建了一個賬戶閉包,并將返回的三個函數(shù)分別賦值給deposited
、withdrawe
和get_balanceed
??梢酝ㄟ^調(diào)用這些函數(shù)來進行賬戶的存款、取款和查詢余額操作, 而balance
變量被封裝在閉包內(nèi)部,外部無法直接訪問,實現(xiàn)了數(shù)據(jù)的封裝和隱藏。
參考文章:
https://zhuanlan.zhihu.com/p/55949749
到此這篇關(guān)于python函數(shù)閉包概念的文章就介紹到這了,更多相關(guān)python函數(shù)閉包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python+wxPython實現(xiàn)文件名批量處理
在日常的文件管理中,我們經(jīng)常需要對文件進行批量處理以符合特定的命名規(guī)則或需求,本文主要介紹了如何使用wxPython進行文件夾中文件名的批量處理,需要的可以參考下2024-04-04python+Splinter實現(xiàn)12306搶票功能
這篇文章主要為大家詳細(xì)介紹了python+Splinter實現(xiàn)12306搶票功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-09-09解決Python串口接收無標(biāo)識不定長數(shù)據(jù)
這篇文章主要介紹了解決Python串口接收無標(biāo)識不定長數(shù)據(jù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09