• 036 返回函数


    • 函数可以返回具体的值,也可以返回一个函数

    引子

    定义一个普通函数

    >>> def func():
    ...   print("YorkFish")
    ...   return None
    ...
    >>> my_func = func()
    YorkFish
    >>> print(my_func)
    None
    >>> my_func
    >>> 
    

    将函数作为返回值

    • 被返回的函数在函数体内定义
    In [1]: def out_func():
       ...:     def in_func():
       ...:         print("in func")
       ...:         return 100
       ...:     return in_func
       ...:
       ...:
    
    In [2]: f = out_func()
    
    In [3]: print(type(f))
    <class 'function'>
    
    In [4]: print(f)
    <function out_func.<locals>.in_func at 0x000001B9B99D6BF8>
    
    In [5]: f()
    in func
    Out[5]: 100
    
    In [6]: 
    

    带参数列表的返回函数

    >>> def out_func(*args):
    ...   def in_func():
    ...     rst = 0
    ...     for i in args:
    ...       rst += i
    ...     return rst
    ...   return in_func
    ...
    >>> f1 = out_func(1, 2, 3, 4, 5)
    >>> f1()
    15
    >>> f2 = out_func(6, 7, 8, 9, 10)
    >>> f2()
    40
    

    闭包

    • closure
    • 当一个函数在内部定义函数,并且内部函数需要使用外部函数的参数或者局部变量,内部函数被当做返回值之时,相关参数和变量会保存在返回的函数中,这种结果,叫闭包
    • 上方 带参数列表的返回函数 就是一个标准闭包结构

    常见的关于闭包的坑

    >>> def out_func():
    ...   res = []
    ...   for i in range(1, 4):
    ...     def in_func():
    ...       return i * i
    ...     res.append(in_func)
    ...   return res
    ...
    >>> f1, f2, f3 = out_func()
    >>> f1()
    9
    >>> f2()
    9
    >>> f3()
    9
    >>> 
    

    造成上述状况的原因

    • 返回函数引用了变量 ii 并非立即执行,而是等到三个函数都返回的时候才统一使用,此时 i 已经变成了 3,最终调用的时候,返回的都是 3*3
    • 由此可见:返回闭包时,返回函数不能引用任何循环变量

    解决方案

    • 再创建一个函数,用该函数的参数绑定循环变量的当前值
    • 无论该循环变量以后如何改变,已经绑定的函数参数值不再改变
    >>> def out_func():
    ...   def in1(n):
    ...     def in2():
    ...       return n * n
    ...     return in2
    ...   res = []
    ...   for i in range(1, 4):
    ...     res.append(in1(i))
    ...   return res
    ...
    >>> f1, f2, f3 = out_func()
    >>> f1()
    1
    >>> f2()
    4
    >>> f3()
    9
    >>> 
    
  • 相关阅读:
    StrCopy、StrCat、StrPas
    WinAPI: FlashWindow 闪烁窗口
    WinAPI: SetVolumeLabel 设置磁盘卷标
    WinAPI: GetActiveWindow 获取当前活动窗口的句柄
    WinAPI: SetCurrentDirectory、GetCurrentDirectory 设置与获取当前目录
    WinAPI: CreateDirectoryEx 根据模版建立文件夹
    WinAPI: CreateDirectory 建立文件夹
    WinAPI: RemoveDirectory 删除空目录
    WinAPI: GetLogicalDriveStrings 获取系统中存在的逻辑驱动器字符串
    filer.js: 一个 Unix 命令风格的 HTML 5 FileSystem API 封装 V2EX
  • 原文地址:https://www.cnblogs.com/yorkyu/p/12074849.html
Copyright © 2020-2023  润新知