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 中强调的是闭包中的环境变量。
posted @ 2020-08-08 14:43  XiaoLee-C  阅读(150)  评论(0编辑  收藏  举报