今天工作的内容已经完成,于是在公司学习一下午,遇到的闭包作用域的问题一直想不明白,于是问了我们开发他也看了很久才明白(因为他是弄java),然后心里想原来并不是所有人都是聪明的,别人 变成优秀的现在就是因为静下心去研究提升。所以自己想转行煎熬的内心又平静而坚定了。
一、变量闭包作用域
python的闭包是如果在一个内部函数里,对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包
def outer(): x=8 def inner(y): return x + y return inner
下面这个应该是很多人都看过的,但是在我最初看的时候我以为是1,3,9,但是程序运行都是9,debug之后想了好久才明白
def count(): fs = [] for i in range(1,4): def fn(): return i*i fs.append(fn) return fs f1,f2,f3 = count() print(f1()) #9 print(f2()) #9 print(f3()) #9
因为是fs存了fn这个函数,return i*i 这里的i使用了外部函数for循环里面的i,当调用fn函数的时候,for i 里面的i已经循环变成3, fn函数执行的时候去找变量i是i=3的,所以就都是9
想要把上边的结果变成1,4,9可以使用如下方法:
def count(): def f(j): def g(): return j*j return g fs = [] for i in range(1, 4): fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f(),每一次的i都会指向一个g的内容地址 return fs f1,f2,f3 = count() print(f1()) #1 print(f2()) #4 print(f3()) #922:40:53
下面的代码会报错:UnboundLocalError: local variable 'a' referenced before assignment
a = 10 def bar(): print(a) a = 'in bar' bar()
报错的原因是因为python编译的时候发现a局部变量是这样子定义的a = ,没有赋值。
在上面的函数bar中在执行第一条语句的时候,为什么不去访问全局变量a呢这是Python语法的规定,当在函数体中有赋值语句的时候,编译的时候就认为定义了局部变量,从而保证函数封装性
二、global
想要前面的值不报错可以使用global关键字
a = 10 def bar(): global a a = 'in bar' bar() print(a) #in bar
但是使用这种代码得小心了,他很容易改变全局变量的值
三、nonlocal
闭包
def fn(): count = 8 def inner(dt=0): r =count +dt print(r) #8 return inner fn()()
如果上面的代码改动一点点他就会报上面的错:UnboundLocalError: local variable 'a' referenced before assignment,原理是和之前一样的
def fn(): count = 8 def inner(dt=0): count+=dt print(count) return inner fn()() #会报错
如果想要上面的代码不报错可以使用nonlocal关键字如下:
def fn(): count = 8 def inner(dt=0): nonlocal count count =count +dt print(count) return inner fn()() #8
nonlocal关键字使用是,内部函数的变量没有时,可以到外部函数寻找变量。
但是值得注意的是使用nonlocal关键字时,内部函数的变量改变了外部函数的变量也会改变,如下:
name = 'global' def test(): name = 'local' def inner_test(): nonlocal name # global name name = name + '变量' return name print(name) #'local'+'变量' return inner_test() print(name) #'global' print(test()) print(name) #'global'
def funX(): x =5 def funY(): nonlocal x x+=1 return x return funY a = funX() print(a()) #6 print(a()) #7 因为x+=1已经把外部函数的x改成了6 print(a()) #8
所以我感觉global和nonlocal还是少用的好
——————一条薛定谔的咸鱼