目录
内置名称空间
全局名称空间
局部名称空间
加载顺序
查找顺序
作用域 (掌握)
全局作用域
局部作用域
注意点
函数对象 + 作用域应用
补充知识点 (了解)
global 关键字
nonlocal 关键字
注意点:
函数内部的函数只能在函数内部调用, 不能在函数外部调用, 通过接下来的学习你将会知道为什么会出现这种情况.
- def f1():
- def f2():
- print('from f2')
- f2()
- f2() # NameError: name 'f2' is not defined
名称空间 (name spaces): 在内存管理那一章节时, 我们曾说到变量的创建其实就是在内存中开辟了一个新的空间. 但是我们一直在回避变量名的存储, 其实在内存中有一块内存存储变量名与变量间的绑定关系的空间, 而这个空间称为名称空间.
内置名称空间
内置名称空间: 存放 Pyhton 解释器自带的名字, 如 int,float,len
生命周期: 在解释器启动时生效, 在解释器关闭时失效
全局名称空间
全局名称空间: 除了内置和局部的名字之外, 其余都存放在全局名称空间, 如下面代码中的 x,func,l,z
生命周期: 在文件执行时生效, 在文件执行结束后失效
- x = 1
- def func():
- pass
- l = [1, 2]
- if 3> 2:
- if 4> 3:
- z = 3
局部名称空间
局部名称空间: 用于存放函数调用期间函数体产生的名字, 如下面代码的 f2
生命周期: 在文件执行时函数调用期间时生效, 在函数执行结束后失效
- def f1():
- def f2():
- print('from f2')
- f2()
- f1()
加载顺序
由于. py 文件是由 Python 解释器打开的, 因此一定是在 Python 解释器中的内置名称空间加载结束后, 文件才开始打开, 这个时候才会产生全局名称空间, 但文件内有某一个函数被调用的时候, 才会开始产生局部名称空间, 因此名称空间的加载顺序为: 内置 --》全局 --》局部.
查找顺序
由于名称空间是用来存放变量名与值之间的绑定关系的, 所以但凡要查找名字, 一定是从三者之一找到, 查找顺序为:
从当前的所在位置开始查找, 如果当前所在的位置为局部名称空间, 则查找顺序为: 局部 --》全局 --》内置.
- x = 1
- y = 2
- len = 100
- def func():
- y = 3
- len = 1000
- print(f"y: {y}")
- print(f"len: {len}")
- # print(a) # NameError: name 'a' is not defined
- func()
- y: 3 len: 1000
- x = 1
- def func():
- print(x)
- x = 10
- func()
- 10
作用域 (掌握)
域指的是区域, 作用域即作用的区域.
全局作用域
全局作用域: 全局有效, 全局存活, 包含内置名称空间和全局名称空间.
- # 全局作用域
- x = 1
- def bar():
- print(x)
- bar()
- 1
局部作用域
局部作用域: 局部有小, 临时存储, 只包含局部名称空间.
- # 局部作用域
- def f1():
- def f2():
- def f3():
- print(x)
- x = 2
- f3()
- f2()
- f1()
- 2
注意点
需要注意的是: 作用域关系在函数定义阶段就固定死了, 与函数的调用无关.
- # 作用域注意点
- x = 1
- def f1(): # 定义阶段 x=1
- print(x)
- def f2():
- x = 2
- f1()
- f2()
- 1
函数对象 + 作用域应用
- # 作用域应用
- def f1():
- def inner():
- print('from inner')
- return inner
- f = f1() # 把局部定义的函数放在全局之中
- def bar():
- f()
- bar()
- from inner
补充知识点 (了解)
global 关键字
修改全局作用域中的变量.
- x = 1
- def f1():
- x = 2
- def f2():
- # global x # 修改全局
- x = 3
- f2()
- f1()
- print(x)
- 1
- x = 1
- def f1():
- x = 2
- def f2():
- global x # 修改全局
- x = 3
- f2()
- f1()
- print(x)
- 3
nonlocal 关键字
修改局部作用域中的变量.
- x = 1
- def f1():
- x = 2
- def f2():
- # nonlocal x
- x = 3
- f2()
- print(x)
- f1()
- 2
- x = 1
- def f1():
- x = 2
- def f2():
- nonlocal x
- x = 3
- f2()
- print(x)
- f1()
- 3
注意点:
在局部想要修改全局的可变类型, 不需要任何声明, 可以直接修改.
在局部如果想要修改全局的不可变类型, 需要借助 global 声明, 声明为全局的变量, 即可直接修改.
- lis = []
- def f1():
- lis.append(1)
- print(f"调用函数前: {lis}")
- f1()
- print(f"调用函数后: {lis}")
调用函数前: []
调用函数后: [1]
来源: https://www.cnblogs.com/nickchen121/p/10761575.html