• Python的闭包函数


     闭包函数

      基于函数对象的概念,可以将函数返回到任意位置去调用 ,但是作用域的关系是在定义完函数时就已经被确定了的,与函数的调用位置无关。

    一、学习闭包函数的必备知识点:
    闭包函数=名称空间与作用域+函数嵌套+函数对象
    核心点:名字的查找关系是以函数定义阶段为准
    二、什么是闭包函数?
    闭:封闭关闭,封闭的函数。指的是该函数是内嵌函数,也就是说被麻袋装起来了
    # 封闭的函数实例:
    # def f1():  # 这里的f1就是麻袋
    #     def f2():  # 这里的f2就是闭函数
    #         pass
        包:包住,在闭的基础上,指的是该函数f2包含对外层函数f1作用域名字的引用。(不是对全局作用域)
    # 闭包函数实例1:
    # def f1():  # 这里的f1就是麻袋
    #     x = 1
    #     def f2():  # 这里的f2就是闭函数
    #         print(x)  # 这里的x引用到了外层函数,所以此时的f2就是闭包函数
    #     f2()
    # x = 222
    # f1()  # 1
    
    # 闭包函数实例2:闭包函数之名称空间与作用域+函数嵌套的应用
    # def f1():  # 这里的f1就是麻袋
    #     x = 333333333333333333333
    #     def f2():  # 这里的f2就是闭函数
    #         print(x)  # 这里的x引用到了外层函数,所以此时的f2就是闭包函数
    #     f2()
    # x = 222
    # def foo():
    #     x = 444
    #     f1()
    #
    # foo()  # 333333333333333333333
    
    # 闭包函数实例3:
    # def f1():  # 这里的f1就是麻袋
    #     x = 333333333333333333333
    #     def f2():  # 这里的f2就是闭函数
    #         print(x)  # 这里的x引用到了外层函数,所以此时的f2就是闭包函数
    #     f2()
    # x = 111
    # def bar():
    #     x = 4444
    #     f1()
    # def foo():
    #     x = 2222
    #     bar()
    #
    # foo()  # 333333333333333333333
    
    # 闭包函数实例4:闭包函数之函数对象
    # 思路:只要我拿到f2的内存地址,那么无论我到哪里调用都可以用到。
    # 我想要在全局作用域拿到f2的内存地址。f2就可以在任意的地方调用了。
    def f1():
        x = 333333333333333333333
        def f2():
            print("函数f2的x:",x)
        # print(f2)  # 打印f2的内存地址
        return f2  # 这里注意不要加(),不加()拿到了内存地址
    # 这里的f是全局变量,但是f的值来自局部,打破了层级上的限制。 
    f = f1()  
    # print(f)  # 这里我可以获得到f2的内存地址,<function f1.<locals>.f2 at 0x0000025CC8499670>
    
    # 拿到了f2的内存地址后加括号执行得到结果
    # f()  # 运行结果:函数f2的x: 333333333333333333333
    
    def foo():
        x = 555
        f()
    
    foo()  # 函数f2的x: 333333333333333333333

    三、闭包函数的应用场景?(为什么要有闭包函数?)
    # 四、两种为函数体传参的方式
    # 1、方式一:直接把函数体需要的参数定义成形参,直接传参
    # def f2(x):
    #     print(x)
    # f2(1)
    # f2(2)
    # f2(3)
    
    # 2、方式二:使用闭包函数
    # def f1():  # 包的效果
    #     x = 3
    #     def f2():
    #         print(x)
    #     return f2  # 返回f2的内存地址,把f2内存地址放到全局
    #
    # f = f1()
    # print(f)  # 获得到了f2的内存地址:<function f1.<locals>.f2 at 0x0000013A25559670>
    # f()  # 3
    
    # 把上面的函数写活,修改函数体的参数
    def f1(x):  # 包的效果
        # x = 3  # 这样就写死了,如何写活?
        def f2():
            print(x)
        return f2  # 返回f2的内存地址,把f2内存地址放到全局
    
    f = f1(3)
    print(f)  # 获得到了f2的内存地址:<function f1.<locals>.f2 at 0x0000013A25559670>
    f()  # 3
    # 爬取三个网址的信息
    # import requests
    # response = requests.get("https://www.baidu.com")
    # print(response.text)
    # requests.get("https://www.cnblogs.com/liunaixu/")
    # print(response.text)
    # requests.get("https://www.cnblogs.com/linhaifeng/")
    # print(response.text)
    
    # 优化上面代码:写一个下载的功能,
    # 传参的方案一:
    # import requests
    # def get(url):
    #     # response = requests.get("https://www.baidu.com")
    #     # print(response.text)
    #     response = requests.get(url)
    #     print(len(response.text))
    # get("https://www.baidu.com")
    # get("https://www.cnblogs.com/liunaixu/")
    # get("https://www.cnblogs.com/linhaifeng/")
    
    # 使用闭包函数:方案二
    import requests
    def outter(url):
        # url='https://www.baidu.com' # 不能写死
        def get():
            response = requests.get(url)
            print(len(response.text))
        return get
    
    baidu = outter('https://www.baidu.com')   # 拿到outter的内存地址
    baidu()
    
    bokeyuan = outter('https://www.cnblogs.com/liunaixu/')
    bokeyuan()

     

    # 四、验证closures()函数
    x = 1
    def outer():
        x = 2
        def inner():
            print(x)
        return inner
    func = outer()
    func()  # 2
    # 可以通过函数的closure属性,查看到闭包函数所包裹的外部变量
    print(func.__closure__)
    # (<cell at 0x000002A01FB86B80: int object at 0x00007FFADB77D6C0>,)
     
  • 相关阅读:
    static、final、this、super关键
    细节二:参数、引用类型、实例化
    枚举类型
    单例模式
    细节一:字符串、switch、默认值、数组
    类属性和类方法
    装饰器模式
    TreeSet
    可见参数和增强for以及自动拆装箱
    静态导入
  • 原文地址:https://www.cnblogs.com/liunaixu/p/12607683.html
Copyright © 2020-2023  润新知