浅析:关于go与python中的回调函数和闭包的一点小总结

前言

  • 浅析,仅个人理解,个人总结。
  • 不讨论标准的函数式编程,如果有需要自行科普。
  • 存在借鉴。

先说闭包

  • 广义上:闭包具备以下两个特点:
    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()
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值