美文网首页
内函数﹝Python﹞

内函数﹝Python﹞

作者: import_hello | 来源:发表于2018-12-31 23:25 被阅读0次

    Inner Functions

    转载须注明出处:简书@Orca_J35 | GitHub@orca-j35,所有笔记均托管于 python_notes 仓库

    1. 概述

    内函数是指被嵌套在外层函数内部的函数,也称嵌套函数(Nested Functions)。例如:

    def print_(): # print_ 是外函数
        msg = "python"
        def printer(): # printer是内函数
            print(msg)
        printer() # 调用内函数
    print_() #> python
    

    内层函数可以访问外层函数的局部变量(或参数)。比如,变量 msg 可以被内函数 printer 正常访问。即便存在多层嵌套,最内层的函数同样可以访问最外层函数的局部变量(或参数)。外层函数的局部变量(或参数)在内层函数中被称为非局部(nonlocal)变量,如果需要修改非局部变量,可使用 nonlocal 关键字。

    def print_(): # print_ 是外函数
        msg = "whale"
        def printer(): # printer是内函数
            nonlocal msg
            msg = "dolpin"
            print(msg)
        printer() # 调用内函数
    print_() #> dolpin
    

    下面以两种内函数的使用场景为例,展示内函数的使用方法:

    • 利用内函数可将操作封装(Encapsulation)到上层函数内部
    • 过内函数整合重复出现的代码块

    2. 封装

    Encapsulation

    内函数在上层函数之外不可见,在上层函数外部发生的任何变化都不会影响到内函数。因此,我们可以利用内函数将操作封装到上层函数的内部。在下面这个示例中,即使函数外部存在同名函数,也不会覆盖内函数:

    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
    

    下面这个递归函数进一步展示了内置函数的使用方式。这种设计模式的优点是将参数检查置于上层函数中,在内函数中无需考虑错误检测,单纯进行运算操作即可。

    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

    有时我们可能会在多个不同的地方使用相同的代码块。比如,当你编写一个用于处理文件的函数时,由于实参可以是文件对象或文件名,所以需要两个分支来应对不同的实参,但在这两个分支中必定会出现相同的代码块,此时便可通过内函数来整合重复出现的代码块。

    def process(file_name):
        def _do_stuff(file_process): # 通过嵌套函数整合重复出现的代码块
            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)
    

    以上面的代码为基础,编写一个统计纽约市 WiFi 热点数量的函数(原始数据位于 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. 参考

    相关文章

      网友评论

          本文标题:内函数﹝Python﹞

          本文链接:https://www.haomeiwen.com/subject/zftslqtx.html