zoukankan      html  css  js  c++  java
  • day12. 闭包

    一、概念

    """
    如果内函数使用了外函数的局部变量,
    并且外函数把内函数返回出来的过程,叫做闭包
    里面的内函数是闭包函数
    """

    二、基本语法

    def songyunjie_family():
        father = "王健林"
        def f_hobby():
            print("我们先顶一个小目标,比如赚它一个亿,这是我爸爸{}".format(father))
        return f_hobby
    
    func = songyunjie_family()
    func()
    
    obj = func.__closure__[0]
    print(obj.cell_contents,"<111>")

    三、复杂版本

    def mashengping_family():
        father = "马云"
        jiejie_name    = "aa"
        meimei_name = "bb"
        money = 1000
        
        def jiejie():
            nonlocal money
            money -= 700
            print("还剩下{}元".format(money))
            
        def meimei():
            nonlocal money
            money -= 200
            print("还剩下{}元".format(money))
    
        def big_master():
            return (jiejie,meimei)
        
        
        return big_master
        
    func = mashengping_family()
    print(func)
    # 返回的是元组
    tup = func() # big_master()
    print(tup)   # tup =  (jiejie,meimei)
    # 获取姐姐
    jiejie = tup[0] # jiejie 函数
    # 获取妹妹
    meimei = tup[1] # meimei 函数
    
    # big_master 是闭包函数,是直接被mashengping_family返回出来的
    # jiejie,meimei 是通过big_master间接被返回到函数外面的
    # 调用妹妹
    meimei()  # 调用妹妹函数
    # 调用姐姐
    jiejie()  # 调用姐姐函数
    
    #看它是不是闭包函数,是就可以用
    # cell获取单元格对象结果是一个函数名
    # 加() 运行
    # ### 获取闭包函数使用的变量  __closure__
    res = func.__closure__
    print(res,"<222>")
    #  cell_contents 用来获取单元格对象当中的闭包函数
    jiejie = res[0].cell_contents 
    meimei = res[1].cell_contents
    
    # 通过获取单元格对象 -> 获取单元格对象中的内容 -> 实际的调用
    jiejie()
    meimei()
    
    print(jiejie.__closure__[0].cell_contents)
    print(meimei.__closure__[0].cell_contents)

    四、闭包的特征和意义

    1、特征

    """
    内函数使用了外函数的局部变量
    那么该变量与闭包函数发生绑定,
    延长该变量的生命周期
    """
    def outer(val):
        def inner(num):
            return val + num
        return inner
        
    func = outer(10) # func = inner
    res = func(15)   # res = func(15) = inner(15)
    print(res)
    """
    10实参 -> val 形参
    因为内函数inner是闭包函数,使用了外函数val
    那么该变量val生命周期被延长,没有随着函数调用的结束而释放.
    func(15) 把15这个参数赋值给num这个形参
    res = inner(15)  => return val + num =>10 + 15 => 25
    """

    2、意义

    引入:

    # 模拟鼠标点击次数
    num = 0
    def click_num():
        global num
        num += 1
        print(num)
    
    click_num()
    click_num()
    click_num()
    num = 100
    click_num()
    click_num()

    2.1 使用闭包函数改写点击次数

    闭包的意义:闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问.

    def click_num():
        num = 0
        def func():
            nonlocal num
            num += 1
            print(num)
        return func
    func = click_num()
    func()
    func()
    num = 1000
    func()
    func()
    func()
    func()
    func()

    五、匿名函数

    1 用一句话来表达只有返回值的函数
    """语法:lambda 参数 : 返回值 """
    """追求代码:简洁,高效"""

    1、无参的lambda表达式

    def func():
        return "123"
        
    # 改写
    func = lambda : "123"
    res = func()
    print(res)

    2、有参的lambda 表达式

    def func(n):
        return type(n)
        
    # 改写    
    func = lambda n : type(n)
    print(  func([1,2,3])  )

    3、带有判断条件的lambda 表达式

    def func(n):
        if n % 2 == 0:
            return "偶数"
        else:
            return "奇数"        
            
    func = lambda n : "偶数" if n % 2 == 0 else "奇数"
    res = func(17)
    print(res)
    
    # ### 三元(目)运算符
    """
    语法:
        真值 if 条件表达式 else 假值  如果条件表达式为真,返回真值,否则返回假值
    """
    n = 16
    res = "偶数" if n % 2 == 0 else "奇数"
    print(res)

    4、小练习:传递两个数, 返回较大的那一个

    def func(x,y):
        if x>y:
            return x
        else:
            return y
            
    func = lambda x,y : x if x>y else y
    res = func(200,100)
    print(res)

    六、练习

    #下面代码成立么?如果不成立为什么报错?怎么解决?
    #1
    # a = 2
    # def wrapper():
    #    print(a)
    # wrapper()
    
    #2
    # a = 2
    # def wrapper():
    #     a += 1
    #     print(a)
    # wrapper()
    
    #3
    # a = 2
    # def wrapper():
    #     global a
    #     a += 1
    #     print(a)
    # wrapper()
    
    #4
    # def wrapper():
    #      a = 1
    #      def inner():
    #          print(a)
    #      inner()
    # wrapper()
    
    #5
    # def wrapper():
    #      a = 1
    #      def inner():
    #          a += 1
    #          print(a)
    #      inner()
    # wrapper()
    
    #6
    # def wrapper():
    #     a = 1
    #     def inner():
    #         nonlocal a
    #         a += 1
    #         print(a)
    #     inner()
    # wrapper()
    # a = 2
    # def wrapper():
    #     print(a)
    # wrapper()
    
    # 成立
    1
    # a = 2
    # def wrapper():
    #     a += 1
    #     print(a)
    # wrapper()
    # 不成立 局部变量不能修改全局变量
    # 解决:
    # a = 2
    # def wrapper():
    #     global a
    #     a += 1
    #     print(a)
    # wrapper()
    2
    # a = 2
    # def wrapper():
    #     global a
    #     a += 1
    #     print(a)
    # wrapper()
    # 成立
    3
    # def wrapper():
    #      a = 1
    #      def inner():
    #          print(a)
    #      inner()
    # wrapper()
    # 成立
    4
    # def wrapper():
    #      a = 1
    #      def inner():
    #          a += 1
    #          print(a)
    #      inner()
    # wrapper()
    # 不成立
    # 要通过 nonlocal引入 a
    # def wrapper():
    #      a = 1
    #      def inner():
    #          nonlocal a
    #          a += 1
    #          print(a)
    #      inner()
    # wrapper()
    5
    def wrapper():
        a = 1
        def inner():
            nonlocal a
            a += 1
            print(a)
        inner()
    wrapper()
    # 成立
    6

     

  • 相关阅读:
    Python is 和 == 的区别, 编码和解码
    Python数据类型之字典
    Python中的基本数据类型之列表与元组初步了解
    Python中基本数据类型与对字符串处理的方法
    Python中的循环体
    Python的历史与基本知识入门
    web前端面试题库
    canvas绘图实现浏览器等待效果
    HTML5 Web Worker的使用
    思维题-方案数
  • 原文地址:https://www.cnblogs.com/kongxiangqun/p/13347897.html
Copyright © 2011-2022 走看看