zoukankan      html  css  js  c++  java
  • python之函数作用域、嵌套以及闭包

    我们首先回忆一下Python代码运行的时候遇到函数是怎么做的,从Python解释器开始执行之后,就在内存中开辟里一个空间,每当遇到一个变量的时候,就把变量名和值之间对应的关系记录下来,但是当遇到函数定义的时候,解释器只是象征性的将函数名读如内存,表示知道这个函数存在了,至于函数内部的变量和逻辑,解释器根本不关心。

      等执行到函数调用的时候,Python解释器会再开辟一块内存来储存这个函数里面的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量回储存在新开辟出来的内存中,函数中的变量只能在函数内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。

    我们给这个‘存放名字与值的关系’的空间起了一个名字-------命名空间。

    代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间;

    在函数的运行中开辟的临时的空间叫做局部命名空间。

    在python中,名称空间三种:

    • 全局名称空间
    • 局部名称空间(临时)
    • 内置名称空间




    作用域:

    • 全局作用域:作用于全局名称空间 内置名称空间
    • 局部作用域:作用于局部名称空间(临时)


    取值顺序:就近原则,单向从小到大范围
    局部名称空间 ---> 全局名称空间 ---> 内置名称空间


    加载顺序
    内置名称空间 ---> 全局名称空间(当程序执行时) ---> 局部名称空间(当函数调用的时候)

    局部名称空间 对全局名称空间的变量可以引用,但是不能改变。

    如果你在局部名称空间对一个变量进行修改,那么解释器会认为你的这个变量在局部中已经定义了。

    global

    • 1.在局部名称空间声明一个全局变量
    • 2.在局部名称空间可以对全局变量进行修改


    实际中
    不常用

    nonlocal

    • 相当于子函数对父函数的变量进行修改。
    • 此变量不能是全局变量
    • # 在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,
    • # 并且引用的哪层,从那层及以下此变量全部发生改变。
    # global
        # 1,在局部名称空间声明一个全局变量。
    # def func2():
    #     global name
    #     name = 'alex'
    # func2()
    # print(name)
    
        # 2,在局部名称空间可以对全局变量进行修改。
    # count = 1
    # def func1():
    #     global count
    #     count = count + 1
    #     print(count)
    # func1()
    # print(count)
    global
    # nonlocal
    # def func1():
    #     count = 666
    #     def func2():
    #         print(count)
    #     func2()
    # func1()
    nonlocal

    函数嵌套

    def func1():
        count = 666
        def inner():
            print(count)
            def func2():
                nonlocal count
                count += 1
                print('func2',count)
            func2()
            print('inner',count)
        inner()
        print('func1',count)
    func1()
    #  666  func2 667  inner 667  func1 667
    

      

    函数名的应用:

    • 1. 函数名就是函数的内存地址
    • 2. 函数名可以做为变量
    • 3. 函数名可以做为函数的参数
    • 4. 函数名可以当作函数的返回值
    • 5. 函数名可以做为容器类类型的元素


    像上面的函数名这种,叫第一类对象

    • 1. 可在运行期创建
    • 2. 可用作函数参数或返回值
    • 3. 可存入变量的实体。
     1. 函数名就是函数的内存地址
    # def func1():
    #     print(666)
    #
    # print(func1)  #<function func1 at 0x0000028BEC62C1E0>
    
    # 2. 函数名可以做为变量
    # f1 = func1
    # f1()
    
    
    # 3. 函数名可以做为函数的参数
    # def func1():
    #     print(666)
    #
    # def func2(x):
    #     x()  # func1()
    #
    # func2(func1)
    
    # 4. 函数名可以当作函数的返回值
    # def wraaper():
    #     def inner():
    #         print('----inner  ')
    #     return inner
    #
    # ret = wraaper()  # inner
    # ret()
    #
    # def func2():
    #     print('in the func2')
    #
    # def func3(x):
    #     print('in the func3') # x = func2
    #     return x
    #
    # f1 = func3(func2)  # func2
    # f1()
    
    # 5. 函数名可以做为容器类类型的元素
    # def func1():
    #     print('in func1')
    #
    # def func2():
    #     print('in func2')
    #
    # def func3():
    #     print('in func3')
    #
    # l1 = [func1, func2, func3, ]
    # for i in l1:
    #     i()
    
    # 像上面的函数名这种,叫第一类对象
    

      

    globals() 返回全局变量的一个字典
    locals() 返回当前位置的局部变量的字典

    # globals()  locals()
    
    # def func1():
    #     pass
    # print(globals())
    # print(locals())
    
    
    def func1():
        a = 2
        b = 3
        print(globals())
        print(locals())
    func1()
    

      

    闭包: 内层函数对外层函数的变量(非全局变量)的引用,并返回, 这样就形成了闭包。

    闭包的作用:
    当程序执行时,遇到了函数执行,他会在内存中开辟一个空间,局部名称空间。如果这个函数内部形成了闭包,
    那么他就不会随着函数的结束而立马消失。

    # def wrapper():
    #     name = 'alex'
    #     def inner():
    #         print(name)
    #     print(inner.__closure__)  # 判断是否闭包(<cell at 0x00000181FD0ED8E8: str object at 0x00000181FD00CE68>,)
    #                                     # 不是闭包返回None
    #     inner()
    #     return inner
    #
    # wrapper()
    
    name = 'alex'
    def wrapper(n):
        # 相当于 n = 'alex'
        def inner():
            print(n)
        print(inner.__closure__)  # 闭包
        inner()
        return inner
    
    wrapper(name)
    

      

  • 相关阅读:
    Java Web 网络留言板2 JDBC数据源 (连接池技术)
    Java Web 网络留言板3 CommonsDbUtils
    Java Web ConnectionPool (连接池技术)
    Java Web 网络留言板
    Java Web JDBC数据源
    Java Web CommonsUtils (数据库连接方法)
    Servlet 起源
    Hibernate EntityManager
    Hibernate Annotation (Hibernate 注解)
    wpf控件设计时支持(1)
  • 原文地址:https://www.cnblogs.com/eaoo/p/9488145.html
Copyright © 2011-2022 走看看