內(nèi)函數(shù)﹝Python﹞

Inner Functions

轉(zhuǎn)載須注明出處:簡書@Orca_J35 | GitHub@orca-j35,所有筆記均托管于 python_notes 倉庫

1. 概述

內(nèi)函數(shù)是指被嵌套在外層函數(shù)內(nèi)部的函數(shù),也稱嵌套函數(shù)(Nested Functions)。例如:

def print_(): # print_ 是外函數(shù)
    msg = "python"
    def printer(): # printer是內(nèi)函數(shù)
        print(msg)
    printer() # 調(diào)用內(nèi)函數(shù)
print_() #> python

內(nèi)層函數(shù)可以訪問外層函數(shù)的局部變量(或參數(shù))。比如,變量 msg 可以被內(nèi)函數(shù) printer 正常訪問。即便存在多層嵌套,最內(nèi)層的函數(shù)同樣可以訪問最外層函數(shù)的局部變量(或參數(shù))。外層函數(shù)的局部變量(或參數(shù))在內(nèi)層函數(shù)中被稱為非局部(nonlocal)變量,如果需要修改非局部變量,可使用 nonlocal 關(guān)鍵字。

def print_(): # print_ 是外函數(shù)
    msg = "whale"
    def printer(): # printer是內(nèi)函數(shù)
        nonlocal msg
        msg = "dolpin"
        print(msg)
    printer() # 調(diào)用內(nèi)函數(shù)
print_() #> dolpin

下面以兩種內(nèi)函數(shù)的使用場景為例,展示內(nèi)函數(shù)的使用方法:

  • 利用內(nèi)函數(shù)可將操作封裝(Encapsulation)到上層函數(shù)內(nèi)部
  • 過內(nèi)函數(shù)整合重復出現(xiàn)的代碼塊

2. 封裝

Encapsulation

內(nèi)函數(shù)在上層函數(shù)之外不可見,在上層函數(shù)外部發(fā)生的任何變化都不會影響到內(nèi)函數(shù)。因此,我們可以利用內(nèi)函數(shù)將操作封裝到上層函數(shù)的內(nèi)部。在下面這個示例中,即使函數(shù)外部存在同名函數(shù),也不會覆蓋內(nèi)函數(shù):

def outer(num1):
    def _inner_increment(num1):  # Hidden from outer code
        return num1 + 1
    num2 = _inner_increment(num1)
    print(num1, num2)
    
def _inner_increment(num1):
    return num1 + 99

outer(10) #> 10 11

下面這個遞歸函數(shù)進一步展示了內(nèi)置函數(shù)的使用方式。這種設計模式的優(yōu)點是將參數(shù)檢查置于上層函數(shù)中,在內(nèi)函數(shù)中無需考慮錯誤檢測,單純進行運算操作即可。

def factorial(number):
    # Error handling
    if not isinstance(number, int):
        raise TypeError("Sorry. 'number' must be an integer.")
    if not number >= 0:
        raise ValueError("Sorry. 'number' must be zero or positive.")

    def inner_factorial(number):
        if number <= 1:
            return 1
        return number*inner_factorial(number-1)
    return inner_factorial(number)

# Call the outer function.
print(factorial(4)) #> 24

3. DRY

Don't repeat yourself

有時我們可能會在多個不同的地方使用相同的代碼塊。比如,當你編寫一個用于處理文件的函數(shù)時,由于實參可以是文件對象或文件名,所以需要兩個分支來應對不同的實參,但在這兩個分支中必定會出現(xiàn)相同的代碼塊,此時便可通過內(nèi)函數(shù)來整合重復出現(xiàn)的代碼塊。

def process(file_name):
    def _do_stuff(file_process): # 通過嵌套函數(shù)整合重復出現(xiàn)的代碼塊
        for line in file_process:
            print(line)
    if isinstance(file_name, str):
        with open(file_name, 'r') as f:
            _do_stuff(f)
    else:
        _do_stuff(file_name)

以上面的代碼為基礎,編寫一個統(tǒng)計紐約市 WiFi 熱點數(shù)量的函數(shù)(原始數(shù)據(jù)位于 NYC Wi-Fi Hotspot Locations,請使用 CSV 格式)。

def process(file_name):

    def _do_stuff(file_process):
        wifi_locations = {}

        for line in file_process:
            values = line.split(',')
            # Build the dict and increment values.
            # values[1] is Borough
            wifi_locations[values[1]] = wifi_locations.get(values[1], 0) + 1

        all_locations = sum(wifi_locations.values())
        max_key = 0
        for name, key in wifi_locations.items():
            if key > max_key:
                max_key = key
                name_of_Borough = name

        print(f'There are {all_locations} WiFi hotspots in NYC, '
              f'and {name_of_Borough} has the most with {max_key}.')

    if isinstance(file_name, str):
        with open(file_name, 'r', encoding="utf_8") as f:
            _do_stuff(f)
    else:
        _do_stuff(file_name)


process("NYC_Wi-Fi_Hotspot_Locations.csv")
#> There are 6411 WiFi hotspots in NYC, and MN has the most with 1603.

4. 擴展閱讀

5. 參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 〇、前言 本文共108張圖,流量黨請慎重! 歷時1個半月,我把自己學習Python基礎知識的框架詳細梳理了一遍。 ...
    Raxxie閱讀 19,602評論 17 410
  • Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 14,259評論 0 38
  • 這篇筆記記錄的知識點:函數(shù)的基本概念自定義函數(shù)函數(shù)的幾種參數(shù) 編程的三種方式:1.OOP 面向?qū)ο缶幊?,萬物皆對象...
    古月半半閱讀 1,098評論 0 2
  • 第二天,黎艾還是不依不饒—— 樓樓,你就陪我去唄?抱著樓柔的胳膊不肯松開,臉貼在樓柔的胸口。 樓柔正要說什么,黎艾...
    沉了個魚閱讀 463評論 0 0
  • 1、開始努力學習英語(3年內(nèi)學好并運用) 2、開始學習理財(定投基金-經(jīng)濟學-會計學-金融學-金融市場) 3、建立...
    海闊天空Sophie閱讀 218評論 0 1

友情鏈接更多精彩內(nèi)容