一文掌握Python內部函數:函數作為返回和閉包

2025年03月17日02:33:07 科技 1510

一文掌握Python內部函數:函數作為返回和閉包 - 天天要聞

Python 中,函數被認為是一等公民,這意味着它們可以像對待任何其他對象一樣對待。這種對一類函數的支持允許使用高階函數,這些函數可以接受其他函數作為參數或返回函數作為結果。這個強大的功能增強了 Python 編程的靈活性和表現力,允許更動態和功能化的編程模式。

為了理解為什麼這些能力是有用的,編寫一個返回其參數的恆等式函數。

def identity(number): 
  return number

identity(10)

#10

現在編寫另一個函數來求平方。

def square(number):
  return number**2

square(6)

#36

現在,將這兩種功能組合到一個函數中。為此,可以將這兩個函數編寫為另一個函數的內部函數。

Python 內部函數:

在 Python 中,內部函數是在另一個函數的主體中定義的函數。它也稱為嵌套函數。們的例子中:

def doWithNumber(number, squareIt = False):

  # identity function as inner function of doWithTheNumber
  def identity(): 
    return number

  # square function as inner function of doWithTheNumber
  def square():
    sq = number**2
    return sq

  # if else block to execute one of the function
  if squareIt == True:
    return square()
  else:
    return identity()

內部函數的作用域在外部函數內,這意味着它可以訪問外部函數的變量和參數。

在上面的例子中, identity()square() 被定義在 doWithNumber(number, squareIt= False) .內部函數可以訪問外部函數的變量和參數,例如,兩者都 i可以訪問 number ,但反之則不然, doWithNumber(number, squareIt= False) 無權訪問 哪個是 的內部變量 square() 。這稱為詞法範圍或閉包。

內部函數在各種場景中都很有用,例如:

  1. 封裝:內部函數允許我們將一個功能封裝在另一個函數的範圍內,將相關代碼保持在一起並與程序的其餘部分分開。上面的函數 doWithNumber(number, squareIt= False) 是封裝的一個很好的例子。
  2. 閉包:內部函數可以創建閉包,這些函數可以記住封閉範圍內的值,即使它們不再存在。這允許在函數調用之間保留狀態。
  3. 裝飾器:內部函數通常用於裝飾器中,這是一種通過用附加功能包裝函數或類來修改它們的行為的方法。內部函數用作包裝器,將所需的功能添加到原始函數中。

返回函數和閉包:

一個函數可以返回另一個函數。例如,可以稍微修改我們的 modifyNumber 數字函數以返回內部函數而不是執行它們。

def modifyNumber(squareIt = False):

  # identity function as inner function of doWithTheNumber
  def identity(number): 
    return number

  # square function as inner function of doWithTheNumber
  def square(number):
    sq = number**2
    return sq

  # if else block to execute one of the function
  if squareIt == True:
    return square
  else:
    return identity

現在,如果執行外部函數,這將為提供另一個函數。請記住,它不會執行任何函數,而是會提供另一個可執行函數。

justPrint = modifyNumber()

上面的代碼將返回我們內部函數 identity(number) 。現在我以用參數調用 justPrint 了。

justPrint(15)

#15

Or

squareNumber= modifyNumber(True)

squareNumber(25)

#625

這裡發生了什麼?

首先,當調用 squareNumber = modifyNumber(True) 它時,它會設置 squareIt = True .

然後它定義了我們的兩個函數 identity()square() .

然後它運行 if-else 塊,因為 squareIt = True ,該塊返回 square ;這是一個函數。

現在 squareNumber = square 相當於。

def squareNumber(number)
  sq = number**2
    return sq

因此,當調用 squareNumber(25) 它時,它返回了 625。

閉包是與內部函數和返回函數相關的重要概念。當嵌套/內部函數從其包含(封閉)函數的作用域引用變量時,即使封閉函數已完成執行,也會發生閉包。

比如之前的函數只能返回 identity 和 square,如果想添加額外的功能怎麼辦?修改一下函數。

def modifyNumber(power):
 def raisePower(number):
  return number ** power

 return raisePower

如果我們調用外部函數

identity = modifyNumber(1)

該函數將返回到另一個函數,即 raisePower .請記住,返回的是尚未執行的函數。為了執行它,必須調用它。

identity(10)
#10
identity(25)
#25

為什麼當調用 identity(10) 時返回 10。因已經看到設置 identity = modifyNumebr(1)power = 1 and 它的集合 identity = raisePower ,它等價於

def identity(number):
  return number ** power

但是raisePowe函數沒有名為 power 的變量。該變量 power 位於函數的作用域 modifyNumebr 內,該函數已完成執行。

現在調用 identity(10) 的時候,它將如何執行這一行代碼 return number ** power ,它如何獲取它的值 power = 1

在 Python 中,當外部函數完成執行並返回內部函數時,它會將內部函數與其封閉環境或閉包一起打包。這意味着函數對象保留其包含作用域中定義的所有變量和名稱的引用。這允許內部函數稍後訪問和使用這些變量,即使外部函數已完成其執行並且這些變量通常超出範圍。

這有點像父母給孩子留下遺產。即使父母可能已不復存在,孩子仍然可以訪問所有繼承的資產。

可以根據需要多次調用我們的外部函數。

squareNumber = modifyNumber(2)
cubeNumber =  modifyNumber(3)
rootNumber = modifyNumber(0.5)

可以隨心所欲地調用我們的內在功能。

squareNumber(10)
#100
squareNumber(5)
#25
cubeNumber(3)
#27
rootNumber(25)
#5.0
rootNumber(16)
#4.0

或者我們可以將這種內部功能與嵌套的俄羅斯娃娃進行比較。可以嵌套儘可能多的函數。

def eventPlanner(evenName):
  print(f'Welcome to {evenName}')
  listOfParticipant = []
 
  def register(name):
    listOfParticipant.append(name)
    print(listOfParticipant)
    
    listOfTask = []
    def addTask(task):
      listOfTask.append(task)
      print(listOfTask)
    
    return addTask
  return register

添加了三層功能,一個在另一個內部。這就像一個洋蔥,調用一個層會讓我們返回到另一個具有層的函數。

如果調用第一層,它將返回一個註冊函數。

fareRegistration = eventPlanner("1st School Fair")

#Welcome to 1st School Fair

現在可以調用第二層。它將打印已註冊人員的列表,並返回給我們一個任務功能。

enamTasks = fareRegistration("Enam")

# ['Enam']

似乎只有一名會員註冊了票價。讓再註冊一個。

kalamTasks = fareRegistration("Kalam")

#['Enam', 'Kalam']

這裡需要注意的一件事是,由於閉包,它為我們打印了兩個名稱,儘管外部函數完成了它的執行,但它提供了直接的內部函數,直到變量的最新狀態。

enamTasks("visit tea stall")
#['visit tea stall']

enamTasks("visit book stall")
#['visit tea stall', 'visit book stall']

enamTasks("attend Magic Show")
#['visit tea stall', 'visit book stall', 'attend Magic Show']

同樣,可以為同樣註冊了票價的 Kalam 先生添加任務。

kalamTasks("Perform Magic")
#['Perform Magic']

總之,這些是 Python 中強大的概念。例如,內部函數允許我們在另一個函數的主體中定義函數,從而提供了一種封裝相關功能並保持代碼模塊化和組織化的方法。內部函數可以訪問封閉函數的變量和參數,使它們能夠利用和操作其包含範圍內的數據。

從其他函數返回函數為我們的代碼增加了另一層靈活性。它允許我們創建高階函數,根據特定要求生成和自定義函數。這種能力使我們能夠編寫更通用和可重用的代碼,並促進函數式編程模式。

當內部函數保留對其封閉作用域的引用,捕獲必要的變量和名稱時,就會形成與返回函數密切相關的閉包。這種機制使內部函數能夠訪問和利用其包含環境的狀態,即使在封閉函數完成執行之後也是如此。閉包為函數提供持久性和上下文,允許它們保留特定於其創建點的數據和行為。

這些概念使我們能夠編寫模塊化、可重用和可定製的功能,從而增強代碼的可讀性、可維護性和效率。無論我們是將它們用於數據封裝、函數工廠、回調還是其他目的,理解和利用內部函數、返回函數和閉包都可以擴展我們的編程工具包,並使我們能夠為各種問題編寫優雅而有效的解決方案。

科技分類資訊推薦

「張灣智警」上崗!無人機變身 「空中 110」 - 天天要聞

「張灣智警」上崗!無人機變身 「空中 110」

晨曦中,數公里外的路口突發擁堵,一架印有「張灣智警」標識的無人機從機庫起飛,通過空中喊話疏導車流,同時將車牌識別畫面,實時推送至地面執法終端。這一幕高效協同的智慧警務場景,正是「張灣智警」無人機系統融入城市治理的日常縮影。
聯想憋了40年的大招:自研5nm芯片上市,這次真沒放鴿子 - 天天要聞

聯想憋了40年的大招:自研5nm芯片上市,這次真沒放鴿子

最近科技圈最熱鬧的事,莫過於聯想在自家新平板上塞了顆"中國芯"。這事要擱五年前,網友能把鍵盤敲出火星子——畢竟在很多人印象里,聯想除了組裝電腦就是賣手機,突然掏出顆5納米芯片,比四川變臉還讓人意外。說起聯想和芯片的恩怨情仇,那真是三天三夜嘮
國產手機沖高端:別光顧着堆料,先學會把價格打上去 - 天天要聞

國產手機沖高端:別光顧着堆料,先學會把價格打上去

最近翻看Counterpoint的2025年一季度手機市場報告,有個數據看得人直嘬牙花子:蘋果手機的平均售價還是816美元,相當於5800多塊人民幣,而小米的均價才155美元,摺合人民幣1100出頭。這價格差得,都能買五台小米湊個"五福臨門
moto razr 60系列三款新機發佈,3499元起售 - 天天要聞

moto razr 60系列三款新機發佈,3499元起售

繼此前moto方面確認,新款小摺疊razr 60系列即將5月8日在國內市場正式發佈後,陸續在預熱活動中公布的產品端相關信息也吸引了眾多消費者的關注。昨日官方正式發佈了razr 60系列三款機型,其中包含一款被命名為razr 60 Pro的新機,該系列機型的售價則從3499元起跳,參與國補後最低僅需2999元。外觀方面,razr 60系列三款機型...
微軟工程師揭秘 Windows 剪貼板優化方式:是如何獲得最佳性能的 - 天天要聞

微軟工程師揭秘 Windows 剪貼板優化方式:是如何獲得最佳性能的

IT之家 5 月 9 日消息,據外媒 Neowin 今日報道,微軟高級工程師雷蒙德・陳在微軟網站的專欄《The Old New Thing》更新博文,他詳細說明了 Windows 本地剪貼板與其他剪貼板管理器的不同之處,並解釋了這種設計為何有益。IT之家註:Windows 提供了默認的剪貼板,可以通過「設置」開啟,也可以通過 Win + V 快捷鍵直接打開。
上線「隨申兌」、擴大「免申即享」範圍……上海無感化服務讓企業輕裝上陣 - 天天要聞

上線「隨申兌」、擴大「免申即享」範圍……上海無感化服務讓企業輕裝上陣

不用自己申請,補貼、獎勵等「絲滑」入賬……上海大力推進的「免審即享」,通過大數據分析、人工智能輔助等工具,將政策精準送到企業身邊。上海正加力提速推進2025年優化營商環境「十大攻堅突破任務」,聚焦企業需求最迫切、協同推進要求高的十個事項,加力推出新一批增量舉措,合力解決營商環境建設中的「老大難」問題。上...
二十年前的586電腦,奔III處理器+Win98系統,閑魚賣2680元 - 天天要聞

二十年前的586電腦,奔III處理器+Win98系統,閑魚賣2680元

之前我寫了個九十年代的海爾電腦機箱,閱讀量挺高的,你們愛看這玩意?那就繼續回憶殺,再寫另一個「收藏級」的586老電腦,自帶純平顯示器。它就是二十五年前的聯想天禧6622電腦,居然是大全套收藏級成色,主機箱、顯示器、鍵盤、光驅、軟驅一應俱全,
消息稱三星顯示最早下月啟動三星電子首款三摺疊手機顯示面板量產 - 天天要聞

消息稱三星顯示最早下月啟動三星電子首款三摺疊手機顯示面板量產

IT之家 5 月 9 日消息,韓媒 daily.hankooki 當地時間今日報道稱,三星顯示預計最早 6 月、最晚 7 月開始量產三星電子首款三摺疊手機(IT之家註:即所謂的 Galaxy G Fold)的顯示面板。▲ 三星顯示 Flex G 三摺疊概念設備報道指出,由於三摺疊手機在整體智能手機市場尚屬新形態,因此三星顯示的面板產量初期預計落在 20~30
Retroid Pocket Mini V2 安卓遊戲掌機發佈,1399 元 - 天天要聞

Retroid Pocket Mini V2 安卓遊戲掌機發佈,1399 元

IT之家 5 月 9 日消息,Retroid 今日推出安卓遊戲掌機 Pocket Mini V2,迭代機型主要解決初代的顯示問題,更換到該公司 Pocket Classic 掌機的同款 3.92 英寸 AMOLED 屏幕,其餘配置參數一致,目前僅提供黑色,官網首發售價 1399 元。Retroid Pocket Mini V2 搭載高通驍龍 865 處理器,