python 函数式编程-闭包
1、基础知识保证我们写出业务代码,而且我们不考虑太多的封装性;高阶知识保证,可以去更好的封装包,类库,提供给其他人使用
2、高阶知识
- 函数式编程
- 闭包
- 什么是函数式编程?
- 什么是闭包?
3、python中一切结皆对象。所以函数也是对象。
- 函数可以赋值给一个变量,变量的类型是个函数function
-
def curve_pre(): pass a = curve_pre print(type(a)) # [Running] python -u "/Users/anson/Documents/Project/python_ToolCodes/test20.py" # <type 'function'>
- 调用函数变量,执行该函数,返回的该函数计算结果
-
def curve_pre(): def curve(x): return x*x return curve f = curve_pre() print(f)#返回的是一个函数&函数可以赋值给一个变量 print(f(2))#调用返回的函数 # [Running] python -u "/Users/anson/Documents/Project/python_ToolCodes/test20.py" # <function curve at 0x1078b0140> # 4
- 变量a从内到外层找,逐渐从小作用域到大作用域去找,从精确作用域到概括作用域,即优先级从内层函数局部变量->外层函数局部变量->最外层变量
-
a = 100#3、外层没有,去更外层找 def curve_pre(): a = 50#2、没有内层a,去外层找a def curve(x): a = 1#1、先找这个a return a*x*x return curve f = curve_pre() print(f) print(f(2))
由此引入什么是闭包?闭包=函数+环境变量,把a定义在标志1的位置,也就是函数内部,不叫闭包,顶多算个函数调用,定义在函数的外部,也就是3的位置,那也不叫闭包
- 放在内层2的位置,为什么叫闭包?
def curve_pre(): a = 50 def curve(x): return a*x*x return curve a = 1 f = curve_pre() print(f.__closure__) print(f.__closure__[0].cell_contents) print(f(2)) # [Running] python -u "/Users/anson/Documents/Project/python_ToolCodes/test20.py" # (<cell at 0x103603750: int object at 0x7fe15b708d68>,) # 50 # 200
改了a=1,也不起作用,前面说过的使用优先级。注意闭包的内容,f.__closure__,是把函数调用的现场给保存下来了,闭包=函数+环境变量(a=50,func=curve)
- 函数闭包的需要注意什么?
-
def f0(): a = 50 def f1(x): a=1#造成了不是闭包,闭包=环境变量(f0()层定义的a=50)+函数f1(x) return a*x*x return f1 f = f0() print(f.__closure__) print(f.__closure__[0].cell_contents) print(f(2)) # [Running] python -u "/Users/anson/Documents/Project/python_ToolCodes/test21.py" # None # Traceback (most recent call last): # File "/Users/anson/Documents/Project/python_ToolCodes/test21.py", line 10, in <module> # print(f.__closure__[0].cell_contents) # TypeError: 'NoneType' object has no attribute '__getitem__'
正确的做法是,不要再内层定义a,这样就没有环境变量了!!!!!!,闭包的2个必要元素缺少一个了,怎么还会是闭包!!!!!!
-
def f0(): a = 50 def f1(x): c=1 return a*x*x return f1 f = f0() print(f.__closure__) print(f.__closure__[0].cell_contents) print(f(2)) # [Running] python -u "/Users/anson/Documents/Project/python_ToolCodes/test21.py" # (<cell at 0x10a3df750: int object at 0x7f963de06158>,) # 50 # 200
这样改或者注释掉f1(x)中定义的a 就可以了
- 闭包是用来干什么的,使用场景是什么?
- 计算旅行者当前所处的位置,起点origin=0
非闭包 origin = 0 def go(step): global origin #声明origin为gloabl,记录旅行者当前的位置 new_pos = origin+step origin = new_pos return new_pos print(go(3)) print(go(2)) 输出: 3 5
闭包 origin = 0 def go_pre(pos): def go(step): nonlocal pos#声明pos 为 nonlocal new_pos = pos + step pos = new_pos return new_pos return go f = go_pre(origin) print(f(3)) print(f(2)) 输出 3 5 ⚠️python2没有nonlocal,python3才有
- 闭包主要用在Javascript 和python python 中强调的是闭包中的环境变量。