zoukankan      html  css  js  c++  java
  • 闭包

    closure:闭包的意思
    闭包特点:
      1.>函数的嵌套定义,就是函数定义里面有另外一个函数的定义
      2.>外部函数返回内部函数的引用<引用地址>
      3.>内部函数可以使用外部函数提供的自由变量/环境变量 <顺序是先去找自己的位置参数,看看是否有同名,如果没有就向外扩展一层,继续这个过程.直到找到>
    这就是闭包的三个特点

    概念:内部函数 + 自由变量 构成的 整体 这是IBM 开发网站的一个说法
    理解:内部函数 + 外部函数提供给内部函数调用的参数.

    def func(num1):
        # 外部函数  的变量称之为自由变量/环境变量 内部函数也可以使用
        print('in func', num1)
    
        def func_in(num2):
            print('in func_in', (num1 + num2))
    
        # return func_in()# 这样就会调用func_in函数了
        # 返回func_in的引用地址 外部就可以进行调用func_in函数了
        return func_in
    
    
    # 因为func_in函数并没有被调用
    # func()  # in func
    # 接收外部函数func 返回值return是 内部函数func_in的引用
    f = func(99)
    f(100)

    闭包求线性方程:

    # ---------------------普通函数实现---------------------------------->
    # def line1(k, x, b):
    #     print('y = %d' % (k * x + b))
    #
    #
    # line1(1, 100, 1)
    # line1(1, 50, 1)
    # ---------------------------闭包实现-------------------------------->
    
    
    def line(k, b):
        def line_in(x):
            print('y = %d' % (k * x + b))
    
        return line_in
    
    
    # l1 = line(1, 1)
    # l1(100)
    # l1(50)
    
    l2 = line(2, 2)
    l2(100)
    l2(50)
    
    """
    l1,l2一样的代码,一样的函数参数,结果不一样,因为他们的环境变量/自由变量不一样
    闭包的概念:自由变量 + 内部函数
    """

    修改自由变量:

    # -----------------------------------------------修改自由变量:了解即可---------------------------------->
    def line(k, b):
        # data = [k]
        def line_in(x):
            # py3 提供的关键字 专门用来修改自由变量
            # 非本地变量  非本地不一定是全局变量,也可能是另外一个函数内部的内部变量<本地变量>
            nonlocal k
            # py2中没有这个关键字,只能将需要修改的变量放到列表中<间接>
            # data[0] += 1
            k += 1  # 不可变类型的k需要使用nonlocal 可变类型<就是[],{},字典等,>的不需要加nonlocal
    
            print('y = %d' % (k * x + b))
    
        return line_in
    
    
    l1 = line(1, 1)
    # l1(9)  # local variable 'k' referenced before assignment 本地变量在赋值之前被引用了
    
    # ------------------------扩展: 查看闭包中的资自由变量的值--------------------------->
    
    # print(l1.__closure__)
    # # (<cell at 0x0000017096A086A8: int object at 0x00000000658460E0>,
    # <cell at 0x0000017096A08708: list object at 0x00000170969D4C08>,
    # <cell at 0x0000017096A086D8: int object at 0x00000000658460E0>)
    # print(l1.__closure__[0].cell_contents)
    # print(l1.__closure__[1].cell_contents)
    # print(l1.__closure__[2].cell_contents)
    
    """
    推荐的经典书籍:
    《流畅的python》
    《Python核心编程》 第二版  不要看第三版 
    
    要求:硬着头皮看两遍
    
    """
    
    
    def make_avg():
        data = list()
    
        def addnumber(value):
            data.append(value)
            total = sum(data)
            # print(data)  加print进行调试理解
            return total / len(data)
    
        return addnumber
    
    
    # myavg = make_avg()
    # print(myavg(100))
    # print(myavg(200))
    # -------------------------------------------可变类型与不可变类型----------------------------------------------------->
    # str1 = 'lll'
    # str1[0]=6  # TypeError: 'str' object does not support item assignment  变量创建之后它内部的元素不能二次赋值就是  不可变类型
    
    list1 = [1, 2, 3]
    list1[0] = 33  # 内部元素可以被二次赋值,就是可变类型
  • 相关阅读:
    ORACLE数据库——触发器的创建和使用
    Oracle——游标的创建和使用
    Oracle数据库和表的操作
    JavaScript中的this,call,apply使用及区别详解
    jQuery插件开发的五种形态小结
    前端图片上传预览
    location.pathname:返回URL的域名(域名IP)后的部分。
    使用Selectivizr让IE6~8支持CSS3
    respond.js有什么作用?
    截取url参数
  • 原文地址:https://www.cnblogs.com/huaibin/p/12101060.html
Copyright © 2011-2022 走看看