参考资料:https://www.imooc.com/code/6059
闭包:
这一小节是Python进阶教程中的第一个重难点,也是Python“函数式编程”的关键章节。要点清单:
-
-
- 正确理解“函数式编程”的思想
-
-
-
- 深刻理解为什么要引入“闭包概念”
-
-
-
- 熟记“闭包”的Python代码范式
-
-
-
- 灵活运用闭包方法到程序开发中
-
要点概括:
- 在
函数内部
定义的函数和外部定义的函数是一样的,只是他们无法被外部访问
- 将函数 g 的定义移入函数 f 内部,可以
防止其他代码调用
函数g - 内层函数
引用了外层函数的变量
(参数也算变量),然后返回内层函数
的情况,称为闭包(Closure)
- 闭包的
特点
是返回的函数还
引用了外层函数的局部变量,所以,要正确使用
闭包,就要
确保引用的局部变量
在函数返回后不能变
.—>>>方法是:若在闭包外有循环
,需要对“闭包”再进行一次闭包操作。因此,返回函数不要引用任何循环变量,或者后续会发生变化的变量。
- 在
4.函数范式
考察下面的函数 f:
def f(j):
def g():
return j*j
return g
它可以正确地返回一个闭包g,g所引用的变量j不是循环变量,因此将正常执行。
在count函数的循环内部,如果借助f函数,就可以避免引用循环变量i。
5. 参考代码:
def count():
fs = []
for i in range(1, 4):
def f(j):
def g():
return j*j
return g
r = f(i)
fs.append(r)
return fs
f1, f2, f3 = count()
print f1(), f2(), f3()
实际运行结果:
>>> def count():
... fs = []
... for i in range(1, 4):
... def f(j):
... def g():
... return j*j
... return g
... r = f(i)
... fs.append(r)
... return fs
... f1, f2, f3 = count()
File "<stdin>", line 11
f1, f2, f3 = count()
^
SyntaxError: invalid syntax
>>> f1,f2,f3=count()
>>> print f1(), f2(), f3()
File "<stdin>", line 1
print f1(), f2(), f3()
^
SyntaxError: invalid syntax
>>> print(f1(),f2(),f3())
1 4 9
`>>> print(f1)
<function count.<locals>.f.<locals>.g at 0x7fd8113a89e0>
>>> print(f1())
1
>>>
“SyntaxError: invalid syntax
”:
- invalid syntax —> 无效语法; 无效的语法;
在这里是视f1,f2,f3
为1个tuple,因为count函数返回的是一个关于函数的list,为了验证这次猜想,我在unbuntu下的命令行进行了如下操作,验证了
我的猜想:
(base) yupengfei@yupengfei-X550VX:~$ python
Python 3.7.6 (default, Jan 8 2020, 19:59:22)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.>>> def count():
... fs = []
... for i in range(1, 4):
... def f(j):
... def g():
... return j*j
... return g
... r = f(i)
... fs.append(r)
... return fs
...
>>> print(count())
[<function count.<locals>.f.<locals>.g at 0x7fd81133e170>, <function count.<locals>.f.<locals>.g at 0x7fd81133e050>, <function count.<locals>.f.<locals>.g at 0x7fd81133e200>]
>>> f1=count()
>>> print(f1)
[<function count.<locals>.f.<locals>.g at 0x7fd81133e050>, <function count.<locals>.f.<locals>.g at 0x7fd81133e170>, <function count.<locals>.f.<locals>.g at 0x7fd81133e200>]
>>> print(f1())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'list' object is not callable
>>> f1,f2,f3=count()
>>> print(f1,f2,f3)
<function count.<locals>.f.<locals>.g at 0x7fd8113a8d40> <function count.<locals>.f.<locals>.g at 0x7fd8113a89e0> <function count.<locals>.f.<locals>.g at 0x7fd8113a8dd0>
>>> print(f1(),f2(),f3())
1 4 9
>>>
其他的一些小问题:
—>关于(base)
-
安装 anaconda 后Linux的终端界面前部出现(base)字样:https://www.cnblogs.com/HISAK/p/12919234.html
-
任意目录,source activate xxx 进入虚拟环境,
-
任意目录,source deactivate 退出虚拟环境
(base) yupengfei@yupengfei-X550VX:~$ source deactivate
DeprecationWarning: 'source deactivate' is deprecated. Use 'conda deactivate'.
yupengfei@yupengfei-X550VX:~$
课后复习:牛刀小试----->对带参数为list类型的函数进行闭包
>>> def afun(x):
... def bfun():
... print('hello '+str(x))
... return x+x
... return bfun
...
>>> a=['aaa','bbb','cccc',['ddd','eee'],'fff']
>>> fatest=afun(a)
>>> print(fatest())
hello ['aaa', 'bbb', 'cccc', ['ddd', 'eee'], 'fff']
['aaa', 'bbb', 'cccc', ['ddd', 'eee'], 'fff', 'aaa', 'bbb', 'cccc', ['ddd', 'eee'], 'fff']
>>> print(a)
['aaa', 'bbb', 'cccc', ['ddd', 'eee'], 'fff']
>>>
课后复习:牛刀小试----->与相应的未进行闭包的带参数为list类型的函数进行对比
>>> def afun(x):
... print('hello '+str(x))
... return x+x
...
>>> a=['aaa','bbb','cccc',['ddd','eee'],'fff']
>>> afun(a)
hello ['aaa', 'bbb', 'cccc', ['ddd', 'eee'], 'fff']
['aaa', 'bbb', 'cccc', ['ddd', 'eee'], 'fff', 'aaa', 'bbb', 'cccc', ['ddd', 'eee'], 'fff']
>>> # 输出的第二行为返回值 a+a
>>> # 接下来输出 a 的值测试 a 是否发生了改变
>>> print(str(a))
['aaa', 'bbb', 'cccc', ['ddd', 'eee'], 'fff']
>>> # a未发生改变
>>> print(afun(a))
hello ['aaa', 'bbb', 'cccc', ['ddd', 'eee'], 'fff']
['aaa', 'bbb', 'cccc', ['ddd', 'eee'], 'fff', 'aaa', 'bbb', 'cccc', ['ddd', 'eee'], 'fff']