闭包就是在函数内再定义一个函数,并作为结果返回。
需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了 f() 才执行。我们来看一个例子:

  1. def count():
  2. fs = []
  3. for i in range(1, 4):
  4. def f():
  5. return i*i
  6. fs.append(f)
  7. return fs
  8. a, b, c = count()

你可能认为调用a()b()c()结果应该是149,但实际结果是:

  1. >>> a()
  2. 9
  3. >>> b()
  4. 9
  5. >>> c()
  6. 9

全部都是9!原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9

具体细节参看: 代码可视化
image.png

练习

利用闭包返回一个计数器函数,每次调用它返回递增整数:

  1. def createCounter():
  2. j=0
  3. def counter():
  4. nonlocal j
  5. j=j+1
  6. return j
  7. return counter
  8. counterA = createCounter()
  9. print(counterA(), counterA(), counterA(), counterA(), counterA())
  10. # 1 2 3 4 5

为什么要用 nonlocal 呢?因为 j 是不可变类型,虽然在 counter() 中能传进来,但无法修改,所以要定义成 nonlocal 类型。