zoukankan      html  css  js  c++  java
  • Python中的名称空间以及作用域

    名称空间介绍:

    当Python解释器启动时,会自动开辟一块内存空间。每当遇到一个变量名的时候,就会把变量名和值的关系记录下来存到这块内存空间中。

    我们给这个存放名称与值的关系的空间起了个名字,叫做——名称空间。

    当函数定义时,解释器只把函数名读入内存,不关心函数内的具体代码。

    当函数调用时,解释器就会另开一个内存空间,存放这个函数里面的变量。当函数调用结束时,就会清空这个函数内所有内容。

    代码在执行时创建的存放变量与变量值关系的内存空间,叫做全局名称空间

    函数调用时,额外开辟的内存空间,叫做局部名称空间

    还有一种名称空间,叫做内置名称空间,这个空间存放的是Python定义好的名称,比如:len, max, min, sorted, bin, oct, hex等之类大家熟悉的名称。

    名称空间里面包含哪些:

      内置名称空间:Python解释器提前定义好的名称,已经存入内置名称空间。

      全局名称空间:if,for,while,无论创建多少层,在里面创建的变量,都存放在全局名称空间中。

      局部名称空间:函数内创建的变量都属于局部名称空间。

    名称空间的生命周期:

      全局名称空间:代码文件执行时创建,代码执行结束销毁。

      局部名称空间:函数调用时创建,函数执行结束时自动销毁。

      内置名称空间:Python解释器启动时创建,Python解释器关闭时销毁。

    名称空间的查找顺序:

      名称查找的第一步,找到自己的位置(大前提)。

      如果自己在全局中,则查找顺序为:全局名称空间 >>> 内置名称空间

      如果自己在局部中,则查找顺序为:局部名称空间 >>> 全局名称空间 >>> 内置名称空间

      注意:函数在定义阶段,名称的查找顺序已经固定,不会因为函数的调用位置变化而变化。

       

    def index():
        x = 111
        print(x)
    
    def index2():
        print(x)
        
    x = 10
    index() 
    index2()
    
    >>> 111
    >>> 10
    
    说明:
      index调用时,
    print(x)时,先查找index函数内的局部名称空间,局部名称空间中有x这个名称,取x的值打印。 index2调用时,创建index2局部名称空间,查找index2函数内的局部名称空间有没有x这个名称,发现没有,就查找比局部名称空间大的名称空间,在全局名称空间中发现有x,即取x=10的值打印。

    练习一:

    x = 111
    def f1():
        x = 222
        def f2():
            x = 333
            def f3():
                # x = 444
                def f4():
                    # x = 555
                    print(x)
                x = 777
                f4()
                # x = 777
            f3()
        f2()
    f1()
    
    >>> 777

    练习二:

    def func():
        x = 1
        def index():
            print(x)
        return index
    
    res = func()
    x = 999
    res()
    
    >>>  1
    
    说明:func函数的返回时index,  res = func(),则res为func函数的返回值,res就是func的内部函数index,注意func返回值没有()。
    函数名()表示调用,返回函数名表示返回这个函数对象。当res()时,表示调用index函数。
    print(x),在index的局部名称空间中,没有x,就往上层找,在func的局部名称空间中,找到了名称x,即把 1打印。找到时不会再向上找。x=999为全部名称空间。即:函数定义时已经确定了名称查找顺序。
    函数在定义阶段查找名字的顺序就已经固定了 不会因为函数的调用位置变化而改变(******)

    练习三:

    x=111
    def outer():
        def inner():
            print('from inner',x)
        return inner
    f=outer()
    x = 222
    f()
    
    >>>'from inner' 222

    练习四:

    x=111
    def outer():
        def inner():
            print('from inner',x)
        return inner
    f=outer()
    def func():
        x=333
        f()
    func()
    
    >>> 'from inner' 111

    Python中的作用域分为两种:

    全局作用域:全局有效:内置名称空间、全局名称空间

    局部作用域:局部有效:局部名称空间

    局部中修改全局变量:

      在局部中,如果全局变量是可变类型,在局部中可以直接修改。如列表,可以通过append修改。但是不能直接复制修改。

    x = []
    def func():
        x.append(1)
    
    func()
    print(x)
    
    >>> [1]

      如果全局变量是不可变类型,局部中是不能修改的。

    x = []
    def func():
        x = [1,2]
    
    func()
    print(x)
    
    >>> []

      除非使用global关键字,可以在局部中直接修改全局变量的值。

    x = 1
    def func():
        global x
        x = [1,2]
    
    func()
    print(x)
    
    >>> [1, 2]

    在局部中修改局部变量:

      通过nonlocal可以在局部中修改局部变量的值。

    # nonlocal  局部修改局部
    def func():
        x = 1
        def index():
            nonlocal x
            x = 2
        index()
        print(x)
    func()
    
    >>> 2
    
    说明:如果不声明nonlocal x, 就不能修改局部变量x的值,打印出来的x为1.

    global: 局部修改全局,想改多个时,可在变量间用 ,隔开:global x, y, z

    nonlocal: 局部修改全局,想改多个时,可在变量间用 ,隔开:nonlocal x, y, z

      

      

  • 相关阅读:
    计算机网络基础
    计算机网络之应用层
    计算机网络之传输层
    计算机网络之网络层
    计算机通信之数据链路层
    fastjson =< 1.2.47 反序列化漏洞浅析
    你没有见过的加密
    CTF MD5之守株待兔,你需要找到和系统锁匹配的钥匙
    Redis 4.x 5.x 未授权访问
    redis安装
  • 原文地址:https://www.cnblogs.com/KbMan/p/11166955.html
Copyright © 2011-2022 走看看