函数命名空间与作用域

147 阅读3分钟

名称空间

1.概念
    就是用来存放各个变量名及其与数据值的绑定关系的地方
name = 'jason'
    # 在内存中申请一块内存空间存储'jason'这个数据值,再申请一块名称空间存储 name 这个变量名和它与'jason'的绑定关系。之后要想使用就只需要去名称空间中查找 name 以此来锁定jason
del name
    # 删的不是数据值,而是变量名及其与数据值的绑定关系
2.分类
    2.1.内置名称空间
    	python解释器运行就会立即创建的空间
        python内置方法都存在于此(lenprintinput2.2.全局名称空间
    	运行py文件过程中产生的名字都存在于此
        # 普通代码里面的变量名,分支结构里面的变量名,循环结构里面的变量名,定义函数的函数名(不包括函数体内部的变量名),定义类的类名
    2.3.局部名称空间
    	函数体代码运行过程中产生的变量名都存在于此
3.存活周期
    内置名称空间:解释器运行(创建)  解释器关闭(销毁)
    全局名称空间:py文件运行(创建)  py文件结束(销毁)
    局部名称空间:函数体代码运行(创建)  函数体代码结束(销毁)

名字的查找顺序

"""查找名字之前一定要先看自己在哪个名称空间"""
1.当前在全局名称空间
	全局名称空间	 >>>  内置名称空间
2.当前在局部名称空间
	局部名称空间   >>>   全局名称空间  >>>:	内置名称空间
名字的查找顺序默认情况下不能颠倒只能是	局部>>>:全局>>>:内置
 # 逐级向上

名称空间的作用域

1.内置名称空间
	在程序任意位置都可以使用(全局有效)
2.全局名称空间
	在程序任意位置都可以使用(全局有效)
3.局部名称空间
	在各自的局部空间可以使用(局部有效)

局部名称空间的复杂情况

1.各个局部名称空间之间默认不共享名字
    def f1():
        name = 'jason'
        print(age)
    def f2():
        age = 19
        print(name)
    f1()  # 报错
    f2()
2.特殊情况
    x = 1
    def fun1():
        x = 2
        def fun2():
            x = 3
            def fun3():
                x = 4
                print(x)
            fun3()
        fun2()
    fun1()  # 4
3.
    name = 'jason'
    def func():
        print(name) 
        name = 'jasonNB'
    func()   # 报错  此时不会向全局中找name,因为 ‘函数在定义阶段名字的查找顺序就已经固定死了’,name未在局部变量中定义就调用。
报错原因类似于
    print(name)  # 未定义就调用
    name = 'jasonNB'  

global与nonlocal关键字

1. global
    1.1.
        money = 999  # 需求:在局部名称空间中修改money的值
        def fun():
            money = 1000
            print(money)
        fun()  # 1000
        print(money)  # 999  并没有完成修改,全局中的money还是999

    1.2   def fun():
            global money  # global可以在局部名称空间中操作全局的money
            money = 1000
            print(money)
        fun()  # 1000
        print(money)  # 1000  已经修改成功

    1.3    l1 = [1, 2, 3, 4, 5]
        def func():
            l1.append(113)
        func()
        print(l1)  #  [1, 2, 3, 4, 5, 113]  
    1.4  s1 = '&jason&'
        def fun1():
            global s1
            s1 = 'jason'
            print(s1)
        fun1()  # jason
总结 : 局部修改全局名称空间中不可变类型的数据,需要使用关键字global声明,如果是可变类型 则无需关键字声明
2.nonlocal
	def fun1():
        x = 100
        l1 = [1,2]
        def fun2():
            nonlocal x
            x = 999
            l1.append(3)
        fun2()
        print(x)
        print(l1)
    fun1()  # 999  [1, 2, 3]
总结:局部修改父级局部名称空间中不可变类型的数据,需要使用关键字nonlocal声明,如果是可变类型 则无需关键字声明。