三大推导式
闭包
>>> def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
>>> f = lazy_sum(1,3,5,7,9)
>>> f
<function lazy_sum.<locals>.sum at 0x0000029DF192B158>
>>> f()
25
>>> f2 = lazy_sum(1,3,5,7,9)
>>> f == f2
False
在函数lazy_sum
中又定义了函数sum
,并且,内部函数sum
可以引用外部函数lazy_sum
的参数和局部变量,当lazy_sum
返回函数sum
时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”
>>> def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
>>> f1, f2, f3 = count()
>>> f1()
9
>>> f2()
9
>>> f3()
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()
return fs
>>> f1, f2, f3 = count()
>>> f1()
1
>>> f2()
4
>>> f3()
9
- 一个函数可以返回一个计算结果,也可以返回一个函数(称为返回函数)。
- 返回一个函数时,牢记该函数并未执行,而是直到调用了
f()
才会执行(若参数发生变化,则以最后的值来确定返回值) - 当一个函数返回了一个函数后,其内部的局部变量还被新函数引用
- 每次调用外部函数都会返回一个新的函数,即使传入相同的参数
- 返回函数中不要引用任何循环变量,或者后续会发生变化的变量。
练习
利用闭包返回一个计数器函数,每次调用它返回递增整数:
>>> def createcounter():
n = 0
def counter():
nonlocal n
n = n+1
return n
return counter
>>> counterA = createcounter()
>>> print(counterA(), counterA(), counterA(), counterA(), counterA())
1 2 3 4 5
>>> print(counterA(), counterA(), counterA(), counterA(), counterA())
6 7 8 9 10
>>> print(counterA(), counterA(), counterA(), counterA(), counterA())
11 12 13 14 15
>>> print(counterA(), counterA(), counterA(), counterA(), counterA())
16 17 18 19 20
- nonlocal不能操作全局变量
- nonlocal 可以对父级作用域的变量进行修改,并且在当前作用域创建