[012]python中的命名空间

字数 729阅读 249

背景

关于python的导入的原因一直不是很理解,上网查了一下这个与命名空间有关。所以写了这样一篇博客梳理其关系。不同的import会对name作用域产生不同的影响,对namespace界定之后,我们的思路也会更加清晰。

什么是命名空间

命名空间就是可以存放很多name的一个space。

python中的name概念与其他语言中的name概念相似,比如java。但是有一点不同的是由于Python是动态语言,所以一个变量可以指向integer,float类型,还可以指向函数。
比如你可以这样写:

   def func():
       print('func executing...')
   f = func

你就可以通过f()访问func函数。

为了了解命名空间首先需要了解module的概念。
一个module 就是一个python文件,一个module可能包含class,fuction,或者许多names。每一个module有它自己的namespaces(我想这就是推出module的原因所在了吧)

同一个命名空间里不能有相同的名字。
每一个命名空间都是孤立的,所以你可以有两个module,比如Inter,FloatingPoint都有一个函数为add()。

关于import

我们常见的import 是 import module,from module import someName,from module import

1.先说import module,这是最简单也是最推荐的一种导入方式。你可以通过module 名字作为前缀来访问其中的变量。

import os
os.path.exist() ## 你必须以os作为开头

2.from module import someName
这会把 someName 从 module 的namespace 导入到当前程序的namespace,由于同一个namespace 只能name不能相同,如果你把Integer.add()导入到当前namespace,且当前namespace有add()函数。那么你是无法通过不用前缀(即add())访问integer.add()的函数。

当然这种情况适合你导入的name少,且当前程序namespace没有要导入的name。

  1. form module import *
    这会把module 中的所有name都导入到当前的namespace,这会导致命名空间污染。(情况在第二点类似,比如有与当前空间相同的name等等问题)

其三者的区别如下图所示:


image.png

scope

scope为程序中的一块区域,在这块区域你不需要通过前缀来访问,换句话说就是name的影响范围。scope有很多种,比如module级别,function级别,python builtins。
比如一个定义在module global namespace中的name,可以被这个module中的function class都访问到,这就相当于java和c++ 其他语言中的全局变量。

这里说明的一点就是一个module就是一个namespace,一个module中可以有很多种scope,class,functio等等。理清他们概念的边界可以减少我们进入陷阱。

推荐阅读更多精彩内容