zoukankan      html  css  js  c++  java
  • 名称空间与作用域

    名称空间与作用域

    1 名称空间(namespaces):

    名称空间是存放各种名字的地方,是对栈区的一种划分

    名称空间可以分为三种:

    内置名称空间,全局名称空间,局部名称空间

    有了名称空间之后,就可以在栈区中存放相同的名字, 而不会互相干扰

    1.1 内置名称空间

    内置名称空间存放的名字:python解释器内置的名字

    内置名称空间的存活周期:python解释器启动则产生,python解释器关闭则销毁

    >>> print
    <built-in function print>
    >>> input
    <built-in function input>
    

    1.2 全局名称空间

    全局名称空间存放的名字:只要不是局部定义、也不是内置的,剩下的都是全局名称空间的名字
    全局名称空间的存活周期:python文件执行则产生,python文件运行完毕后销毁

    x=10
    if 13 > 3:
        y=20
        if 3 == 3:
            z=30
    
    # func=函数的内存地址
    def func():
        a=111
        b=222
    
    class foo:
        pass
    # 其中x,y,z,func,foo都存放于全局名称空间
    

    1.3 局部名称空间

    局部名称空间存放的名字:在调用函数时,运行函数体代码过程中产生的函数内的名字
    局部名称空间的存活周期:在调用函数时存活,函数调用完毕后则销毁

    def func(a,b):
        pass
    
    func(10,1)
    func(11,12)
    func(13,14)
    func(15,16)
    # 上面共产生了四次局部名称空间,也销毁了四次局部名称空间
    

    1.4 名称空间的加载顺序

    内置名称空间>全局名称空间>局部名称空间

    1.5 名称空间的销毁顺序

    局部名称空间>全局名空间>内置名称空间

    1.6 名字的查找优先级:从当前所在的位置向上一层一层查找

    如果当前在局部名称空间:

    先从局部名称空间查找,

    如果不存在,再从全局名称空间寻找,

    如果不存在,再从内置名称空间寻找

    局部名称空间---------->全局名称空间----------->内置名称空间

    如果当前在全局名称空间:

    先从全局名称空间寻找,

    如果不存在,再从内置名称空间寻找

    全局名称空间--------->内置名称空间

    注意点:

    1. 函数定义时会确定函数内名字的值所在的名字空间

      (原因: 定义时需要检查语法)

    2. 定义时只确定使用哪个名称空间的值,而不确定这个名字的值

      (原因: 定义时只检查语法,不需要数值)

    下面为示例 :

    input=333
    def func():
        input=444
        print(input)  # input局部空间内有,使用局部空间的input
    
    func()
    # 查看局部空间的input是否定义了值----->444
    # 444 
    
    
    input=333
    def func():
        print(input) # input局部空间内没有,全局空间内有,使用全局空间的input
    
    func()
    # 查看全局空间的input是否定义了值----->333
    # 333 
    
    def func():
        print(input)# input局部空间内没有,全局空间内也没有,内置空间有,使用内置空间的input
    
    func()
    # 查看内置空间的input是否定义了值-----><built-in function input>
    # <built-in function input>
    
    input=333
    def func():
        input=444
    func()
    print(input)# input全局空间内没有,内置空间有,使用内置空间的input
    # 查看内置空间的input是否定义了值-----><built-in function input>
    # 333
    
    def func():
        print(x)# x局部空间内没有,全局空间内有,使用全局空间的x
    x=111
    
    func()
    # 查看内置空间的input是否定义了值-----><built-in function input>
    # 111
    # 注意:不会报错,若x=111在func()代码执行后,会报错,因为没定义x的值
    
    # 名称空间的"嵌套"关系是以函数定义阶段为准,与调用位置无关
    x=1
    def func():
       print(x)	# x局部空间内没有,全局空间内有,使用全局空间的x
    
    
    def foo():
        x=222
        func()
    
    foo()
    # 1在执行前定义了,不报错
    # 结果: 1
    
    input=111
    def f1():
        def f2():
            print(input)# input局部空间f2()内没有,局部空间f1()内有,使用局部f1空间的input
        input=222
        f2()
    
    f1()
    # 222在执行前定义了,不报错
    # 222
    
    input=111
    def f1():
        def f2():
            input=333
            print(input)# input局部空间f2内有,使用局部f2空间的input
        input=222
        f2()
    
    f1()
    # 333在执行前定义了,不报错
    # 333
    
    input=111
    def f1():
        def f2():
            print(input)# input局部空间f2()内没有,局部空间f1()内没有,全局空间内有,使用全局空间的input
        f2()
    
    f1()
    # 111在执行前定义了,不报错
    # 111
    
    x=111
    def func():
        print(x) # x局部空间内有,使用局部空间的x
        x=222
    
    func()
    # 使用局部空间的x输出,但是x还没定义,不能输出,报错
    # UnboundLocalError: local variable 'x' referenced before assignment
    

    2 作用域

    作用域也就是作用范围,作用域可以分为两类: 全局作用域 和 局部作用域

    2.1 全局作用域:

    全局作用域包含内置名称空间与全局名称空间

    特点:

    1、全局存活
    2、全局有效:被所有函数共享

    x=111
    def foo():
        print(x,id(x))
    
    def bar():
        print(x,id(x))
    
    foo()
    # 111 140726763447392
    
    bar()
    # 111 140726763447392
    
    print(x,id(x))
    # 111 140726763447392
    

    2.2 局部作用域

    局部作用域包含局部名称空间的名字
    特点:

    1、临时存活
    2、局部有效:函数内有效

    def foo(x):
        def f1():
            def f2():
                print(x)
            f2()
        f1()
    
    foo(1)
    # 1
    
    # LEGB
    # local			本地,最内层
    # enclosing		外层嵌套
    # global		全局
    # builtin		内置
    
    
    # global
    def f1():
        # enclosing
        def f2():
            # enclosing
            def f3():
                # local
                pass
    

    3 申明所在名称空间

    如果我们想在局部修改外部的变量,

    可以使用global或nonlocal方法申明变量所属的名称空间,

    之后对这个名字的操作就不再是对本地local的名字进行操作,而是对申明的名字操作

    x=111
    def func():
        x=222
    
    func()
    print(x)
    # 111
    

    3.1 global

    global: 申明后,可以修改全局名称空间中包含的名字对应的值(不可变类型)

    x=111
    def func():
        global x # 声明x这个名字是全局的名字,不要再造新的名字了
        x=222
    
    func()
    print(x)
    # 222
    
    # 对于可变数据类型,没有必要申明global,不申明依旧可以修改全局名称空间中的l
    l=[111,222]
    def func():
        l.append(333)
    
    func()
    print(l)
    

    3.2 nonlocal

    nonlocal: 申明后,可以修改函数外层函数包含的名字对应的值(不可变类型)

    x=0
    def f1():
        x=11
        def f2():
            nonlocal x
            x=22
        f2()
        print('f1内的x:',x)
    
    f1()
    # f1内的x: 22
    
    # 对于可变数据类型,没有必要申明nonlocal,不申明依旧可以修改函数外层函数中的列表
    def f1():
        x=[]
        def f2():
            x.append(1111)
        f2()
        print('f1内的x:',x)
    
    f1()
    # f1内的x: [1111]
    
  • 相关阅读:
    指令
    linux学习之多高并发服务器篇(三)
    linux学习之高并发服务器篇(二)
    linux学习之多高并发服务器篇(一)
    Linux学习之socket编程(二)
    Linux学习之socket编程(一)
    myeclipse中如何修改Servlet模板_day01
    Properties的使用以及配置文件值的获取
    Sql_Server中如何判断表中某字段是否存在
    微博开发流程-01
  • 原文地址:https://www.cnblogs.com/achai222/p/12527294.html
Copyright © 2011-2022 走看看