前言
- 浅析,仅个人理解,个人总结。
- 不讨论标准的函数式编程,如果有需要自行科普。
- 存在借鉴。
先说闭包
-
广义上:闭包具备以下两个特点:
1、可以读取函数内部的变量。
2、让这些变量的值始终保持在内存中。 -
关于这两点我就通过一个叠乘的小案例,一次性都表现出来了。
- 在go中:闭包不仅可以读函数内部的变量,还可以直接修改。
package main import "fmt" func test() func() int { var x int // 对应类型的“零值”,此处为0 return func() int { x++ return x * x } } func main() { f := test() fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) // 输出 16 }
- python:在闭包中如果要捕获并修改外部变量的话需要使用:nonlocal关键字
- 由于python的设计缘故,你不太好使用lambda写出逻辑复杂的匿名函数,而且为了可读性,就先这样吧。
def main(): x = 0 def re_str(): nonlocal x x += 1 return x * x return re_str if __name__ == '__main__': func = main() print(func()) print(func()) print(func()) print(func()) # 输出 16
-
总结一下
- 闭包的应用场景:出于种种原因,我们有时候需要获取到函数内部的局部变量并修改它。
再说回调函数
- 定义(应用场景):当程序跑起来时,应用程序会时常通过API调用库里预先备好的函数。但是有些库函数却要求应用先传给他一个函数,好在合适的时候调用,以完成目标任务。这个被传入、后又被调用的函数被称为回调函数。
- 如果你不太读得懂定义,那么你结合下面的两种实际应用场景,就很好的看懂定义了。
1、主函数中的变量可以通过参数的形式传给回调函数。
2、主函数中的变量不可以通过参数的形式传给回调函数(个人觉得这样的应该更重要一点)。 - 关于以上两点,通过一个小案例吧:
a)、案例需求:通过回调函数将主函数中的切片(列表)的第一个数修改为4。
b)、ps:这里选用的数据类型是切片和列表,原因是:切片在go中作为参数时是引用传递;列表是可变类型,这点挺重要的。
关于第一点:。
- go:
package main import "fmt" //type FuncType func(sli []int, i int) // 也可以通过这种方式定义回调函数 func HandleSli(sli []int, i int) { sli[0] = i } //func Test(sli []int, f FuncType) {} func Test(sli []int, f func(sli []int, i int)) { i := 4 f(sli, i) } func main() { var sli = []int{1, 2, 3} Test(sli, HandleSli) fmt.Println(sli) }
- python:
def handle_lis(l, i): l[0] = i def test(l, f): i = 4 f(l, i) def main(): l = [1, 2, 3] test(l, handle_lis) print(l) if __name__ == '__main__': main()
关于第二点:
-
go
package main import "fmt" //type FuncType func(i int) // 也可以通过这种方式定义回调函数 //func HandleSli(i int) { //sli[0] = i //err //} //func Test(f FuncType) {} func Test(f func(i int)) { i := 4 f( i) } func main() { var sli = []int{1, 2, 3} Test(func(i int) { sli[0] = i }) fmt.Println(sli) }
- 关于这里为了更好的理解,我做个补充:Test()中定义的变量 i 其实类似js回调函数中的 el 和 event。
-
python
# def handle_lis(l, i): # l[0] = i def test(f): i=4 f(i) def main(): l = [1, 2, 3] def handle_lis(i): nonlocal l # 因为是可变类型,不声明也没关系 l[0] = i test(handle_lis) print(l) if __name__ == '__main__': main()