模块导入和重载
- 解释:每一个以.py结尾的Python源码文件都是一个模块,其它的文件可以通过导入一个模块读取这个模块的内容。导入从本质上来讲,就是载入另一个文件。
- 形式:
# vi script1 import sys print(sys.platform) print(2 ** 100) x = 'Spam!' print(x * 8) wq
# ipython3 In [1]: import script1 linux 1267650600228229401496703205376 Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!
默认情况下,导入只会在每次会话的第一次运行,在第一次导入之后,再进行导入操作将不会再工作,甚至在另一个窗口你改变并保存了模块的源码文件。
In [2]: import script1 In [3]: import script1
这是有意设计的结果,导入是一个开销很大的操作,以至于每个文件,每个程序运行不能够重复多余一次。但是如果真的想要Python在同一次会话中再 次运行文件(不停止和重新启动会话),需要调用imp标准库模块中可用的reload函数(Python2内置,Python3不是内置了)
In [4]: from imp import reload In [5]: reload(srcript1) linux 1267650600228229401496703205376 Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam! Out[5]: <module 'script1' from '/usr/local/kaelwork/python/script1.py'>
这里的from语句直接从一个模块中复制出一个名字,reload函数载入并运行了最新文件的最新代码,如果你已经在另一个窗口中修改并保存了的话。这就 允许了你在当前交互会话的过程中编辑并改进代码。reload函数希望获得的参数是一个已经加载了的模块对象的名称,所以如果在重载之前,请确保已经成功 导入了这个模块,值得注意的是,reload函数在模块对象的名称前面还需要加入括号,import则不需要,reload是一个被调用的函数,而import是一个语句!这也就是为什么你必须把模块名称传递给reload函数u作为括号中的参数,并且这也是在重载时得到了额外一行输出的原因。最后一行输出是reload调用后的返回值的打印显示,reload函数的返回值是一个Python模块对象。
模块的显要特性:属性
- 解释:宏观角度上讲,模块扮演了一个工具库的角色,一般意义上来说,模块往往就是变量名的封装,被认作是命名空间。在一个包中的变量名就是所谓的属性。也就是说,属性就是绑定在特定的对象上的变量名(就像一个模块)。
- 形式:一个模块文件的变量名可以通过import和from语句读取,以及reload函数调用
# vi myfile.py title = "The Meaning of Life" wq
# ipython3 In [1]: import myfile In [2]: print(myfile.title) The Meaning of Life
一般来说,这里的点号表达式代表了object.attribute的语法,可以从任意object中取出任意的属性。作为替代方案,可以通过这样的语句从模块文件中获得(实际上是复制)变量名:
# ipython3 In [1]: from myfile import title In [2]: print(title) The Meaning of Life
import和from很相似,只不过增加了对载入组建的变量名的额外的赋值。从技术上讲,from复制了模块的属性,以便属性能够成为接收者的直接变量。因此,能够直接一title(一个变量)引用导入字符串而不是myfile.title(一个属性)引用。
# vi treenames.py a = 'dead' b = 'parrot' c = 'sketch' print(a,b,c) wq
# python3 threenames.py dead parrot sketch
所有的这个文件代码运行起来就和第一次从其他地方导入(无论通过import和from)后一样。这个文件的客户端通过import的到了具有属性的模块,而客户端使用from时,则会获得文件变量名的副本。
# ipython3 In [1]: import threenames //载入整个模块 dead parrot sketch In [2]: threenames.b,threenames.c Out[2]: ('parrot', 'sketch') In [3]: from threenames import a,b,c //复制变量名 In [4]: b,c Out[4]: ('parrot', 'sketch')
一旦模块文件中有多个变量名,内置的dir函数可以获得模块内部的可用的变量名的列表。
In [5]: dir(threenames) Out[5]: ['<strong>builtins</strong>', '<strong>cached<strong>', '</strong>doc</strong>', '<strong>file</strong>', '<strong>loader<strong>', '</strong>name<strong>', '<strong>package</strong>', '</strong>spec</strong>', 'a', 'b', 'c']
你会发现,一些以双下划线开头并结尾的变量名是免费获得的,这些通常都是由Python预定义的内置变量名,对于解释器来说有特定的意义。那些通过代码赋值而定义的变量在dir结构的最后显示。
模块和命名空间
- 模块是Python程序最大的程序结构。通过import语句连接多个模块文件。每个模块文件是一个独立完备的变量包,即一个命名空间。一个模块 文件不能看到其它文件定义的变量名,除非显式地导入了那个文件。每个文件都是一个独立完备的命名空间,即使他们可能拼写相同,一个文件中的变量名是不会与 另一个文件中的变量冲突的。正式由于模块将变量封装为不同的部分,Python具有了能够避免命名冲突的有点。
- 注意:import和from列出模块名时,都是使用了myfile,没有.py后缀,但是当Python寻找实际文件时,在搜索程序上加入后缀名。系统shell命令中,除了import语句中不同加入后缀名,其它都是加入。
- exec运行模块文件,exec内置函数调用,是从交互提示模式启动文件而不必导入以及随后的重载的一种方法,每次exec都运行文件的最新版本,而不需要随后重载。
# ipython3 In [1]: exec(open('script1.py').read()) linux 1267650600228229401496703205376 Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!
但是必须要注意的是,exec的工作机制就好像在调用它的地方粘帖了代码一样,和from一样,对于当前正在使用的变量有潜在的默认覆盖的可能。
In [2]: x = 999 In [3]: exec(open('script1.py').read()) linux 1267650600228229401496703205376 Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam! In [4]: x Out[4]: 'Spam!'
相反基本的import语句每个进程只运行文件一次,并且它会把文件生成到一个单独的模块名称空间中,以便它的赋值不会改变你的作用域中的变量。为模块名称空间分隔付出的代价是,在修改之后需要重载。
0 条评论