前言
命名空间,又名 namesapce,这是一个术语会出现在许多编程语言中。据估计,很多人都知道这个词,但如果你真的说这是什么,你可能会停下来,所以我想 命名空间 有必要了解一下。
[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-AS5LnV2v-1636110810037)(https://upload-images.jianshu.io/upload_images/25002343-23fe95d142cfb8a4.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)]
**4、需要Python学习资料可以是76 年 24 月 59号考试510分 去掉文字加我的伪 ,免费赠送信息!(书太多了,我就随便发一点!**
全局变量 & 局部变量
全局变量和局部变量是我们理解命名空间的开始。让我们先看一个代码:
x = 2def func(): x = 3 print('func x ---> ',x) func()print('out of func x ---> ',x)
该代码输出的结果如下:
func x ---> 3out of func x ---> 2
从上述结果可以看出,运行 func(),输出是 func() 里面的变量 x 引用的对象 3.之后执行代码中的最后一行。这里要区分清楚,前者 x 函数内部的变量输出 x,后一个 x 函数外的变量输出 x,两个变量不相互影响,在各自的作用域发挥作用。
[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-eMMcKHkC-1636110810069)(https://upload-images.jianshu.io/upload_images/25002343-a5bbb117a0557726.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)]
只在函数中工作的变量称为 有了局部变量 “局部” 就有相应的 全部,但后者听起来很歧义,所以它被称为 “全局”。
x = 2def func(): global x = 3 #注意此处 print('func x ---> ',x) func()print('out of func x ---> ',x)
这个代码比上一个代码增加了一个代码 global x,这句话的意思是声明 x 是全局变量,一般来说就是这个 x 和 函数外的 x 是同一个了,所以结果就成了下面这样:
func x ---> 3out of func x ---> 3
乍一看,整体变量似乎很强,可以控制函数的内部和外部,但我们仍然需要注意,整体变量或谨慎使用,因为毕竟,内部和外部是不同的,不要带来混乱。
作用域
作用域,用比较直白的方式来说,就是程序中变量与对象相关的程序,比如我在上面说的, x = 2 和 x = 3 在两个不同的作用域。
通常,作用域分为静态作用域和动态作用域,尽管我们说 Python 它是一种动态语言,但其作用域属于静态作用域,即 Python 变量在程序中的位置决定了变量的作用域。
[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-jspzFSG2-1636110810071)(https://upload-images.jianshu.io/upload_images/25002343-5b4dd4b2ad8c56b3.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)]
在 Python 中作用域分为四个层次:local(局部作用域),enclosing(嵌套作用域),global(全 built - in(内建作用域)。对变量,Python 根据之前的四个层次,我们依次在不同的功能域中找到它们。在上一个代码中,对于变量 x,首先搜索的是函数体内的局部作用域,然后是函数体外的全局作用域,至于这段话具体怎么来理解,请看下面的例子:
def out_func(): x = 2 def in_func(): x = 3 print('in_func x ---> ',x) in_func() print('out_func x ---> ',x) x = 4out_func()print('x == ',x)
仔细观察一下上面的代码和运行的结果,你就会发现变量在不同的范围内进行搜索的规律,是不是感觉这些都是以前被你忽略的呢?
命名空间
维基百科说 命名空间是对作用域的一种特殊抽象,这里我用一个例子来说明:
比如张三在公司 A,他的工号是 李四在公司 B,他的工号也是 111,因为两个人在不同的公司,他们的工作号码可以相同,但不会造成混乱,这里的公司说一个独立的命名空间,如果两个人在一家公司,他们的工作号码不能相同,否则只是看工作号码不知道是谁。
事实上,上述示例的特点是我们使用命名空间的原因。在大型计算机程序中,数百个标志符经常出现,命名空间提供了一个隐藏区域标志符的机制。通过构成相应的命名空间,可以使整个系统更加模块化。
我在开头引用的维基百科的那句话 命名空间是作用域的一种特殊抽象,实际上包含了作用域内的标识符,也用标识符表示。 Python 在中间,命名空间本身的标志符也属于一个更外层的命名空间,因此命名空间也可以嵌套在一起 全局命名空间 下。
[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-hVjSUBXQ-1636110810073)(https://upload-images.jianshu.io/upload_images/25002343-2f1af8bd8ac80075.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)]
简而言之,不同的命名空间可以同时存在,但它们是独立的,不会相互干扰。当然,命名空间可以分为以下几类:
1.本地命名空间:当模块中有函数或类时,每个函数或类定义的命名空间为本地命名空间。当函数返回结果或抛出异常时,本地命名空间结束。
2.全球命名空间:每个模块创建自己的全球命名空间,不同模块的全球命名空间相互独立,不同模块中相同名称的命名空间不会因模块的不同而相互干扰。
3.内置命名空间:当 Python 当它们运行时,它们就存在了。内置函数的命名空间属于内置命名空间,因此我们可以在任何程序中直接操作它们。
[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-V7fVbdTS-1636110810075)(https://upload-images.jianshu.io/upload_images/25002343-3d74edba70e111e0.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)]
在查询命名空间时,还有一套顺序,按照当地命名空间依次进行 ,全球命名空间,内置命名空间。
def fun(like): name = 'rocky' print(locals()) fun('python')
使用本地命名空间 locals 让我们来看看结果:
{'name': 'rocky', 'like': 'python'}
从以上结果可以看出,命名空间中的数据存储结构与字典相同。你可能已经猜到,当我们想访问整体命名空间时,它可以使用 globals。
命名空间还有一个生命周期的问题,就是命名空间什么时候出现,什么时候消失。这很容易理解,也就是说,哪一部分读入内存,哪一部分存在命名空间,比如我们上面说的,Python 启动,建立内置命名空间。