python命名空间

局部命名空间下
def foo():
	a = a
if __name__ == '__main__':
	foo()

报错信息:UnboundLocalError: local variable ‘a’ referenced before assignment

全局命名空间下
if __name__ == '__main__':
	b = b

报错信息:NameError: name ‘b’ is not defined

为什么在不同的作用域下报错信息不一样呢?

要解决这个问题,就必须了解namespace,也就是命名空间。命名空间是变量名和对象本身的映射,就像是人名与人本身的映射一样。共有四种类型的命名空间:

  • 局部命名空间(local):指的是一个函数或者一个类所定义的名称空间;包括函数的参数、局部变量、类的属性等。

  • 闭包命名空间(enclosing function):闭包函数 的名称空间(Python 3 引入)。

  • 全局命名空间(global):读入一个模块(也即一个.py文档)后产生的名称空间。

  • 内建命名空间(builtin):Python 解释器启动时自动载入__built__模块后所形成的名称空间;诸如 str/list/dict…等内置对象的名称就处于这里。

命名空间是何时创建的呢?

  • 内建命名空间在 Python 解释器启动时创建,之后会一直存在;

  • 模块的全局命名空间在模块定义被读入时创建,通常模块命名空间也会保持到解释器退出。

  • 函数调用时产生新的局部命名空间;函数返回结果、抛出异常时释放命名空间,每一次递归都生成一个命名空间。

  • 标识符产生地点决定标识符所处的命名空间。

变量名是何时加入到命名空间的呢?

def foo():
	# 创建了命名空间,但内容为空
	print(locals())
	if True:
		# 将a加入到命名空间
		a = 1
	else:
		# 因为没有运行,所以没有将b加入到命名空间
		b = 2
	print(locals())
	
if __name__ == '__main__':
	foo()
# 运行结果
# {}
# {'a': 1}

从上面这个例子,可以知道,只有赋值语句被执行时,才会将相应的变量名加入到命名空间中。

那么对于a=a,命名空间是如何处理的呢?

查了很多资料,也没有找到答案。但根据已知的内容,我 猜测 局部命名空间和全局命名空间对a=a的处理方式并不同。

  • 局部命名空间
    遇到到a=a时,python解释器发现了变量a,将其加入到命名空间。然后继续执行,从命名空间中找到了未赋值的a来给a赋值,就出现了UnboundLocalError: local variable ‘a’ referenced before assignment错误。
  • 全局命名空间
    遇到到a=a时,未将a加入到命名空间就执行,python解释器在命名空间找不到a,就出现了NameError: name ‘b’ is not defined的错误。

二者的区别就在于a加入到命名空间是在赋值操作前还是在赋值操作后。

参考

命名空间的生命周期
由一个例子到python的名字空间
python命名空间与作用域

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值