今天工作的内容已经完成,于是在公司学习一下午,遇到的闭包作用域的问题一直想不明白,于是问了我们开发他也看了很久才明白(因为他是做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还是少用的好
——————一条薛定谔的咸鱼