闭包

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  # 内部元素可以被二次赋值,就是可变类型
原文地址:https://www.cnblogs.com/huaibin/p/12101060.html