Python作用域与名字空间原理详解

所属分类: 脚本专栏 / python 阅读数: 1602
收藏 0 赞 0 分享

Python具有静态作用域,变量的作用域由它定义的位置决定,而与调用的位置无关。

 a = 2 
def f():
 a = 2

第一行的a的作用域是全局作用域,作用于定义位置后面的所有位置。

第四行的a的作用域是局部作用域,作用于f函数里。

Python能够形成局部作用域的只有函数与类,其他语句不形成局部作用域。

函数与类的局部作用域

def f():
  a = 1
class A:
  b = 2
if 1 == 1:
  c = 3
for _ in range(1):
  d = 4
while True:
  e = 5
  break
print(c, d, e)
try:
  print(a)
except Exception as e:
  print(e)
try:
  print(b)
except Exception as e:
  print(e)

输出结果

 3 4 5
 name 'a' is not defined
 name 'b' is not defined

python动态运行时,每个作用域都有三个名字空间:由局部变量组成的local名字空间,由全局变量组成的global名字空间,以及python内建模块的builtins名字空间,在查询一个变量时,搜索顺序为local->global->builtins,即局部变量屏蔽全局变量,全局变量屏蔽内建变量。

python的global名字空间是动态的,即每遇到一个赋值语句(def与class也属于赋值语句),global名字空间都可能发生变化。

global名字空间的动态变化

 print(dir())
 a = 1
 print(dir())
 b = 2
 print(dir())

输出结果

1 ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
2 ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a']
3 ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'b']

从输出结果可以看出,global名字空间是动态增加的。

这意味着,虽然位于global名字空间的变量叫做全局变量,它的作用范围也不是全局位置,它只作用于第一次赋值之后的位置。因为只有在变量赋值初始化的时候,它才会被加入到global名字空间中。

函数和类搜索的global名字空间是调用位置的global名字空间,与定义位置无关

def f():
  print(a)

try:
  f()
except Exception as e:
  print(e)

a = 2
f()

输出结果

name 'a' is not defined
2

函数f打印全局变量a,a在第9行定义。在第五行调用f的时候,a不在global名字空间中,所以会输出错误信息,在第十行再次调用函数f时,a已经加入了global名字空间,所以能够打印出a。

python为了提高效率,local名字空间是静态实现的,因为对于一个函数来说,它所包含的局部变量是明确已知的。

函数的local名字空间是静态的

a = 4
def f():
  try:
    print(a)
  except Exception as e:
    print(e)
  a = 1
f()

输出结果

 local variable 'a' referenced before assignment

在打印a的时候,在local名字空间中找到了a,但是这时候a并没有赋值初始化,所以抛出异常。这也说明了local名字空间与global名字空间不同,它会在一开始就把所有的局部变量加入到名字空间中。

总结:

1. python是静态作用域,变量初始化的位置决定了它的作用域,而与变量调用的位置无关

2. global名字空间是动态的,不同位置的global名字空间不同,local名字空间是静态的,局部变量在整个局部作用域内可见。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

使用Python写一个量化股票提醒系统

这篇文章主要介绍了小白用Python写了一个股票提醒系统,迷你版量化系统,完美的实现了实时提醒功能,代码简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Python绘制的二项分布概率图示例

这篇文章主要介绍了Python绘制的二项分布概率图,涉及Python基于numpy、math的数值运算及matplotlib图形绘制相关操作技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

Python Learning 列表的更多操作及示例代码

这篇文章主要介绍了Python Learning-列表的更多操作,需要的朋友可以参考下
收藏 0 赞 0 分享

关于python列表增加元素的三种操作方法

这篇文章主要介绍了关于python列表增加元素的几种操作方法,主要有insert方法,extend方法和append方法,每种方法给大家介绍的非常详细,需要的朋友可以参考下
收藏 0 赞 0 分享

如何在python字符串中输入纯粹的{}

这篇文章主要介绍了如何在python字符串中输入纯粹的{}以及python字符串连接的三种方法,需要的朋友可以参考下
收藏 0 赞 0 分享

浅谈Django的缓存机制

这篇文章主要介绍了浅谈Django的缓存机制,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Django 限制用户访问频率的中间件的实现

这篇文章主要介绍了Django 限制用户访问频率的中间件的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

示例详解Python3 or Python2 两者之间的差异

这篇文章主要介绍了Python3 or Python2?示例详解两者之间的差异,在本文中给大家介绍的非常详细,需要的朋友可以参考下
收藏 0 赞 0 分享

Python wxpython模块响应鼠标拖动事件操作示例

这篇文章主要介绍了Python wxpython模块响应鼠标拖动事件操作,结合实例形式分析了Python使用wxpython模块创建窗口、绑定事件及相应鼠标事件相关操作技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

使用Python实现一个栈判断括号是否平衡

栈(Stack)在计算机领域是一个被广泛应用的集合,栈是线性集合,访问都严格地限制在一段,叫做顶(top)。这篇文章主要介绍了使用Python实现一个栈判断括号是否平衡,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多