闭包
例子
代码均以python3为例。
函数f1
内部定义一个函数f2,并且f1函数返回值为内部函数f2,这样在内部函数f2中就可以使用外部函数f1定义的变量a了。以下程序运行结果为4。
- def f1():
- a = 1
- def f2():
- b = 1
- c = a + 1
- return a + b + c
- return f2
- f3 = f1()
- print(f3())
但是,注意在f2函数中不能修改变量a,如果把f2函数中的语句‘c=a+1'修改成'a=a+1',则会报错。
- def f1():
- a = 1
- def f2():
- b = 1
- a = a + 1
- return a + b
- return f2
- f3 = f1()
- print(f3())
解决问题
在python3里面,引入了一个关键字:nonlocal来解决这个问题,告诉系统该变量是在外部定义的。
- def f1():
- a = 1
- def f2():
- nonlocal a
- b = 1
- a = a + 1
- return a + b
- return f2
- f3 = f1()
- print(f3())
修饰器
提出问题
在写代码时,一般不会轻易对已经实现的类或函数进行修改。为了扩充函数功能,可以使用修饰器。
函数f1功能是求两个数之和,现在还想求这两个数之积,又不能修改函数f1,该怎么办?
- def f1(a, b):
- print('两数之和:', a+b)
结果如下:两数之和: 7
- def w1(func):
- def inner(a, b):
- print('两数之积:', a*b)
- func(a, b)
- return inner
- @w1
- def f1(a, b):
- print('两数之和:', a+b)
- f1(3, 4)
结果如下:
两数之积: 12
两数之和: 7
两数之和: 7
原理
python解释器就会从上到下解释代码,步骤如下:
1.def w1(func): ==>将w1函数加载到内存
2.@w1
1.def w1(func): ==>将w1函数加载到内存
2.@w1
执行w1函数 ,并将 @w1 下面的函数作为w1函数的参数,即:@w1 等价于 w1(f1) 所以,内部就会去执行。将执行完的w1函数返回值 赋值 给@w1下面的函数的函数名f1,即将w1的返回值再重新赋值给 f1。些时的f1函数已经不是表面上看到的函数,而是增加了inner函数中的内容,函数功能得到了扩充。