闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。!!
def count ():
fs = []
for i in range(1,4):
def f():
return i*i #变量i
fs.append(f) #在列表fs中添加函数地址
return fs #最终返回三个函数地址,变量i均指向3
f1,f2,f3 = count()
print (f1(),f2(),f3()) #9,9,9,闭包时牢记返回函数不能引用任何循环变量,即内函数f()不能引用外函数count()的循环变量'''
(1)原因是返回函数引用了变量i,f1,f2,f3=count()执行过程如下:
当i=1, 执行for循环, 结果返回函数f的函数地址,存在列表fs中的第一个位置上。
当i=2, 由于fs列表中第一个元素所指的函数中的i是count函数的局部变量,i也指向了2;然后执行for循环, 结果返回函数f的函数地址,存在列表fs中的第二个位置上。
当i=3, 同理,在fs列表第一个和第二个元素所指的函数中的i变量指向了3; 然后执行for循环, 结果返回函数f的函数地址,存在列表fs中的第三个位置上。
所以在调用f1()的时候,函数中的i是指向3的
def count ():
fs = []
for i in range(1,4):
def f(j):
def g(): #创建新函数
return j*j
return g #此时j不是count()变量
fs.append(f(i))
return fs
f1,f2,f3 = count()
print (f1(),f2(),f3()) #1,4,9,利用新函数参数绑定循环变量的值
(2)当i=1时,f(1)即让j指向1,
当i=2时,f(2)即让j指向2,此时j不是count的局部变量,不会影响到i=1是f(1)中j的指向。即函数f的参数绑定循环变量当前的值, 而不是循环变量本身。
(3)
def count ():
fs = []
for i in range(1,4):
def f(i): #指定函数参数
return i*i
fs.append(f(i)) #把f(i)值添加到列表fs中
return fs
f1,f2,f3 = count()
print (f1,f2,f3) #1,4,9