zoukankan      html  css  js  c++  java
  • DAY10 函数的进阶(命名空间,作用域,函数嵌套)

    前提须知(python解释器遇到函数的做法):

      1.从python解释器开始执行后,就在内存中开辟了一块空间(全局命名空间)。

      2.每次遇到一个变量的时候,就会把这个变量名和值得对应关系保存到这个内存的一个字典中,记录下来。

      3.但是遇到函数定义的时候,解释器只会象征性地把函数读入内存,表示知道这个函数的存在,但是对函数内部的“变量”和逻辑毫不关心。

      4.等执行到函数调用的时候,python解释器就会再开辟一块内存来存储函数里面的内存(局部命名空间)。这个时候,才会真正开始关注函数里面有哪些变量,而函数的变量会存储到新开辟的这个内存中。函数的变量只能在函数的内部使用,而且随着函数的执行完毕,这块空间就会被回收,内容就会被清空。

    一.三种命名空间

      1. 全局命名空间

      2. 局部命名空间

      3. 内置命名空间

    从上面的解释,我们可以得出:

    (1)代码开始时,python解释器创建的存储“变量:值”对应关系的内存空间叫做全局命名空间。

    (2)在函数开始执行时,python解释器在内存中新开辟的内存空间叫做局部命名空间。

    (3)内置命名空间,python内置,例如input,print等,在哪里都可以直接拿来使用。

    二.三种命名空间的加载和取值顺序:

      1.加载顺序:

      内置命名空间(程序运行前加载)---> 全局命名空间(程序运行中加载,由上到下)--->局部命名空间(函数调用时加载)

      2.取值顺序:

      在局部调用时:局部命名空间--->全局命名空间--->内置命名空间

      在全局调用时:全局命名空间--->内置命名空间

    #在局部命名空间中:局部》全局》内置
    #在全局命名空间中:全局》内置
    #取值顺序都是单向的,不可逆。
    
    x = 10
    def foo():
        x = 20
        print(x)
    foo()    #局部>全局>内置
    print(x)   #全局>内置
    >>>
    20
    10
    

      

    三.作用域

      作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域等~

      LEGB:

      (1)Local(本地,局部):在局部空间中,即函数定义的变量。

      (2)Enclosing(封闭):用在函数嵌套时。

      (3)Global(全局):在当前这个py文件中

      (4)Builtin(内置):在所有py文件中都可以使用,例如:input,str等。

    四.global关键字

      前提:局部命名空间对全局命名空间的变量可以引用,但是不能修改。

      global作用:

        1. 在局部名称空间声明一个局部变量。

        2. 在局部名称空间可以对全局变量进行修改。

    #一。结合前文的取值顺序,
    count = 1
    def func1():
        print(count)    #取值顺序,局部命名空间(没有)----全局命名空间(有)
    func1()
    >>>
    1
    
    #二。如果在局部作用域中对全局变量进行修改,会如何?
    
    count = 1
    def func1():
        count = count +1
        print(count)
    func1()
    >>>UnboundLocalError: local variable 'count' referenced before assignment
    
    '''
    UnboundLocalError: local variable 'count' referenced before assignment
    如果你在局部命名空间对一个变量进行修改,解释器就会认为这个变量要存在,已经在局部定义;如果没有
    定义,就会引发以上报错。
    '''
    
    # 这个时候就是使用global的场景
    # global的作用:
    '''
    1. 在局部命名空间声明一个局部变量。
    2. 在局部命名空间对全局变量进行修改。
    '''
    
    count = 1
    def func():
        global count
        count = count +1
        print(count)
    func()
    print(count)
    >>
    2
    2

    五.函数嵌套

      函数是python中的一级对象,可以在任何地方使用。包括函数里,此时的作用域属于封闭作用域Enclosing。

      函数名的本质:函数也是一级对象。

      一级对象

      (1)在运行时创建

      (2)能够赋值给变量

      (3)能够作为参数传递给函数

      (4)能够作为函数的返回值

    #函数嵌套范例一
    def f1():
        print('in f1')
        def f2():
            print('in f2')
        f2()
    f1()
    >>>
    in f1
    in f2
    
    #函数嵌套范例二
    def f1():
        def f2():
            def f3():
                print('in f3')
            print('in f2')
            f3()
        print('in f1')
        f2()
    f1()
    >>>
    in f1
    in f2
    in f3
    

      4.1 函数嵌套的作用域链

    #函数作用链(一)
    def f1():
        a = 1
        def f2():
            print(a)      
        f2()
    f1()
    >>>
    1
    
    # 函数作用域(二)
    def f1():
        a = 1
        def f2():
            def f3():
                print(a)
            f3()
        f2()
    f1()
    >>>
    1
    
    # 函数的作用域(三)
    def f1():
        a = 1
        def f2():
            a = 2
            print('a in f2:',a)
        f2()
        print('a in f1:',a)
    f1()
    >>>
    a in f2: 2
    a in f1: 1

      总结以上:就是先从局部命名空间查找,再一级一级向上查找。

    六.nonlocal关键字

      1.在函数的外部必须有这个变量

      2.在内部函数声明nonlocal变量之前,不能再出现同名变量。

      3.在局部作用域修改父级作用域(非全局作用域的更外层作用域),并且引用的哪层,就从那层以下此变量发生变化。

    def f1():
        a = 10
        def f2():
            nonlocal a
            a = 30
        f2()
        print('in the f1:',a)
    f1()
    >>>
    a in f2: 2
    a in f1: 1
    in the f1: 30
    
    
    def f1():
        a = 10
        def f2():
            def f3():
                nonlocal a
                a = 30
                print('in the f3:',a)
            print('in the f2:',a)
            f3()
        f2()
        print('in the f1:',a)
    f1()
    >>>
    in the f2: 10
    in the f3: 30
    in the f1: 30
    

      

  • 相关阅读:
    关于RecyclerView你知道的不知道的都在这了(下)
    关于RecyclerView你知道的不知道的都在这了(上)
    读书笔记--Android Gradle权威指南(下)
    读书笔记--Android Gradle权威指南(上)
    写完批处理脚本,再写个Gradle脚本,解放双手
    写个批处理脚本来帮忙干活--遍历文件夹&字符串处理
    发布开源库到JCenter所遇到的一些问题记录
    swift GCD使用指南
    挣值管理(PV、EV、AC、SV、CV、SPI、CPI)记忆之我见
    一、通过企业账号申请证书
  • 原文地址:https://www.cnblogs.com/hebbhao/p/9488379.html
Copyright © 2011-2022 走看看