zoukankan      html  css  js  c++  java
  • python | 闭包

    python | 闭包

    基础

    作用域

    作用域是程序运行时变量可被访问的范围,定义在函数内的变量是局部变量,局部变量的作用范围只能是函数内部范围内,它不能在函数外引用。
    定义在模块最外层的变量是全局变量,它是全局范围内可见的,当然在函数里面也可以读取到全局变量的。例如:

    num = 10 # 全局变量
    def foo():
        print(num)  # 10

    而在函数外部则不可以访问局部变量。

    def foo():
        num = 10
    print(num)  # NameError: name 'num' is not defined

    嵌套函数

    定义在函数里面的函数称之为嵌套函数(nested function)

    def outer(): # outer是外层函数
        msg = "python"
    
        def inner(): # inner 为内层函数即嵌套函数
            print(msg)
    
        return inner()
    
    outer() # 输出 python

    对于嵌套函数,它可以访问到其外层作用域中声明的非局部(non-local)变量。首先查找本层函数 inner 内部是否有定义,没有发现后开始查找外层作用域的变量

    msg = "global"
    
    def outer(): # outer是外层函数
        # msg = "python"
    
        def inner(): # inner 为内层函数即嵌套函数
            print(msg)
    
        return inner()
    
    outer()

    而当把 outer函数的变量注释后,在全局进行定义,此时就开始查找全局变量

    python 中函数是可以作为变量进行引用的,类似高中数学中的 f(x)计算
    在高中数学复合函数定义中:

    y=f(u), u=g(x),则函数 y=f(g(x))为复合函数,f(u)为外层函数,g(x)为内层函数,u为中间变量
    
    计算顺序应当是先计算内层函数然后结果作为变量来计算外层函数

    闭包

    def outer():  # outer是外层函数
        msg = "python"
    
        def inner():  # inner 为内层函数即嵌套函数
            print(msg)
    
        return inner # 返回 inner 的地址
    
    
    result = outer()
    result() # 输出 python
    print(outer()) # 输出 inner的内存地址
    print(outer()()) # 输出 python和 None
    print(result.func_closure)

    结果

    python
    <function outer.<locals>.inner at 0x103136ea0>
    python
    None

    闭包使得局部变量在函数外被访问成为可能。 return 的函数不加括号返回的是地址。func_closure打印了闭包中包含了哪些外部变量。
    enter description here

    每个函数都有__closure__属性,如果一个函数是闭包的话则会返回一个由 cell 对象组成的元组对象。而 cell 对象的cell_contents属性就是闭包中保存的自由变量

    def adder(x):
        def wrapper(y):
            return x + y
        return wrapper # 返回函数地址
    adder5 = adder(5)
    
    adder5(10) # 输出 10
    adder5(6) # 输出 11
    print(adder.__closure__)
    print(adder5.__closure__)
    print(adder5.__closure__[0].cell_contents)

    结果

    None
    (<cell at 0x106430fd8: int object at 0x1050cf110>,)
    5 # 自由变量

    闭包特点

    一个函数返回的函数对象,这个函数对象执行的话依赖非函数内部的变量值,这个时候,函数返回的实际内容如下:

    1. 函数对象
    2. 函数对象需要使用的外部变量和变量值
      以上就是闭包

    闭包必须嵌套在一个函数里,必须返回一个调用外部变量的函数对象,才是闭包

    最后推荐一个python 可视化运行的网站,对于 python 执行的步骤和存储的变量等很直观
    http://www.pythontutor.com/visualize.html#mode=display

    参考:
    https://www.cnblogs.com/xiaxiaoxu/p/9785687.html
    https://zhuanlan.zhihu.com/p/26934085

  • 相关阅读:
    Openstack Nova 源码分析 — Create instances (nova-conductor阶段)
    openstack nova 源码解析 — Nova API 执行过程从(novaclient到Action)
    Fiddler抓包9-保存会话(save)
    Fiddler抓包10-会话框添加查看get与post请求类型
    Fiddler抓包11-HTTPS证书Actions无法导出问题
    Fiddler抓包7-post请求(json)
    Fiddler抓包8-打断点(bpu)
    Fiddler抓包3-查看get与post请求
    Fiddler抓包4-工具介绍(request和response)
    Fiddler抓包5-接口测试(Composer)
  • 原文地址:https://www.cnblogs.com/hbgzy/p/10971562.html
Copyright © 2011-2022 走看看