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 # 内部元素可以被二次赋值,就是可变类型