名称空间与作用域
目录
一、名称空间的概念
名称空间(namespace)就是用来存储变量名与数据值绑定关系的地方(我们也可以简单的理解为就是存储变量名的地方)
二、分类
在程序执行期间最多会存在三种名称空间
2.1 内建名称空间
伴随python解释器的启动/关闭而产生/回收,因而是第一个被加载的名称空间,用来存放一些内置的名字,eg:
len print input
2.2 全局名称空间
伴随python文件的开始执行/执行完毕而产生/回收,是第二个被加载的名称空间,文件执行过程中产生的名字都会存放于该名称空间中,其中,在py文件中,顶格写的代码都在全局名称空间中, 如下
name = 'kevin' # 变量名name
if True:
a = 1 # 变量名a
while True:
x = 10 # 变量名x
def index(): # 函数名index
pass
2.3 局部名称空间
伴随函数的调用/结束而临时产生/回收,函数的形参、函数内定义的名字都会被存放于该名称空间中
def index(x):
y=3 #调用函数时,才会执行函数代码,名字x和y都存放于该函数的局部名称空间中
2.4 查看
可以调用内建函数globals()和locals()来分别查看全局名称空间和局部名称空间的名字,返回的结果都是字典格式。使用locals()查看时,要在局部查看。
三、名字的查找顺序
第一步、首先先确定你所在的位置
第二步、如果在局部中:局部 >>> 全局 >>> 内置
第三步、如果在全局中:全局 >>> 内置
# 局部
x=100
def func():
x=300
print(x)
func() # 结果是300
# 全局
x=100
def func():
x=300
func()
print(x) # 结果是100
Python支持函数的嵌套定义,在内嵌的函数内查找名字时,会优先查找自己局部作用域的名字,然后由内而外一层层查找外部嵌套函数定义的作用域,没有找到,则查找全局作用域
"""
函数体代码中名字的查找顺序在函数定义阶段就已经固定死了
"""
# x = 888
def index():
# x = 666
def index1():
# x = 555
def index2():
# x = 444
def index3():
# x = 333
def index4():
x = 222
print(x)
index4()
index3()
index2()
index1()
index()
四、名称空间的作用域
作用域就是作用的范围
- 内置的
在任何阶段任何时间都可以使用 (全局有效) - 全局的
在任何阶段任何时间都可以使用 (全局有效) - 局部的
在函数内部阶段使用 (局部有效)
五、global与nonlocal关键字的使用
5.1 global
局部修改全局的
- 修改的是不可变类型,必须使用global关键字声明一下
- 修改的是可变类型,就可以直接修改
1.当全局作用域中的值为不可变类型时
在函数内,无论嵌套多少层,都可以查看到全局作用域的名字
# 局部空间中重新赋值也不会改变全局中x的值,x仍然是100
x = 100
def index():
x = 200
index()
print(x) # x的结果是100
想要在函数内修改全局名称空间中名字的值,需要用到global关键字
x = 100
def index():
# 局部修改全局的变量
global x # 声明变量x为全局的x
x = 200
index()
print(x) # x的结果是200
2.当实参的值为不可变类型时,函数体对该值的修改将会直接反应到原值
x = ['kevin', 'jack']
def index():
# 局部修改全局的变量
x.append('tony')
index()
print(x)
# 输出结果是:['kevin', 'jack','tony']
5.2 nonlocal
内部的局部修改外部的局部
- 如果是不可变类型,必须使用nonlocal关键字声明一下
- 如果是可变类型,就可以直接改变
1.不可变类型
# 对于嵌套多层的函数中,
# 不可变类型时,嵌套内部的赋值改变不了外部的值,x的值是60
def index():
x = 60
def func():
x = 90
func()
print(x)
index() # x的结果是60
# 想要内部的局部修改外部的局部,需要使用nonlocal关键字
def index():
x = 100
def func():
nonlocal x
x = 200
func() # 调用func(),修改index()作用域中名字x的值
print(x) # 在index()作用域查看x
index() # x的结果是90
# nonlocal x会从当前函数的外层函数开始一层层去查找名字x,若是一直到最外层函数都找不到,则会抛出异常。
2.可变类型
# 可变类型
def index():
x = ['a', 'b']
def func():
x.append('c')
func()
print(x) # ['a', 'b', 'c']
index()