模块的创建
定义模块,只要使用文本编辑器,把一些Python代码输入至文本文件中,然后以“.py”为后缀名进行保存,任何此类文件都会被自动认为是Python模块。在模块顶层指定的所有变量名都会变成其属性(与模块对象结合的变量名),并且可以导出供客户端来使用。
模块的使用
客户端执行import或from语句来使用模块,如果模块还没有加载,这两个语句就会去搜索、编译以及执行模块文件程序。主要的差别在于,import会读取整个模块,所以必须进行定义后才能读取它的变量名;from将获取(或者说是复制)模块特定的变量名
如下是两种使用区别:
比如我们一开始定义了一个module1.py模块,如下所示:
# module1.py
def printer(x): # Module attribute
print(x)
我们分别用import和from来使用该模块
import module1
module1.printer('hello world!')
from module1 import printer
printer('hello world!')
from语句其实只是稍稍扩展了import语句而已,它照常导入了模块文件,但是多了一个步骤,将文件中的一个或多个变量名从文件中复制了出来。
from *语句
from module1 import *
printer('hello world!')
from *形式只是多加个步骤,把模块中所有变量名复制到了进行导入的作用域之内。从根本上来说,这就是把一个模块的命名空间融入另一个模块之中;同样地,实际效果就是可以让我们少输入一些。
注意:Python3.0中,这里所述的from *语句形式只能用在一个模块文件的顶部,不能用于一个函数中。
导入只发生一次
模块会在第一次import或from时载入并执行,并且只在第一次如此。这是有意而为之的,因为该操作开销较大。在默认情况下,Python只对每个文件的每个进程做一次操作。之后的导入操作都只会指出已加载的模块对象。
如下,我们先定义simple.py模块
print('hello')
spam = 1
然后我们分别import模块两次,两次之间改变属性的值,如下所示:
import simple
print(simple.spam)
simple.spam = 2
import simple
print(simple.spam)
输出的结果如下:
hello
1
2
我们可以看到,第二次和其后的导入并不会重新执行此模块的代码,只是从Python内部模块表中取出已创建的模块对象。因此,变量spam不会再进行初始化。
import和from是赋值语句
就像def一样,import和from时可执行的语句,而不是编译期间的声明,而且它们可以嵌套在if测试中,出现在函数def之中等。
import将整个模块对象赋值给一个变量名
from将一个或多个变量名赋值给另一个模块中同名的对象
以form复制的变量名会变成对共享对象的引用。就像函数的参数,对已取出的变量名重新赋值,对于其复制之处的模块并没有影响,但是修改一个已取出的可变对象,则会影响导入的模块内的对象。如下所示:
我们先在small.py中定义如下对象:
x = 1
y = [1,2]
from small import x,y
x = 42
y[0] = 42
import small
print(small.x)
print(small.y)
运行结果:
1
[42, 2]
此处,x并不是一个共享的可变对象,但y是。导入者中的变量名y和被导入者都引用相同的列表对象,所以在其中一个地方的修改,也会影响另一个地方的这个对象。
from语句潜在的陷阱
建议:简单模块一般倾向于使用import,而不是from。多数的from语句是用于明确例举出想要的变量,而且限制在每个文件中只用一次from *形式。这样一来,任何无定义的变量名都可被认为是存在于from *所引起的模块内。
何时使用import
当你必须使用两个不同模块内定义的相同变量名的变量时,才真的必须使用import,这种情况下不能使用from。
模块命名空间
文件生成命名空间
在模块文件顶层(也就是不在函数或类的主体内)每一个赋值了的变量名都会变成该模块的属性。
模块语句会在首次导入时执行。
顶层的赋值语句会创建模块属性
模块的命名空间能通过属性__dict__或dir(M)获取
模块是一个独立的作用域(本地变量就是全局变量)
导入和作用域
函数绝对无法看见其他函数内的变量名,除非它们从物理上处于整个函数内
模块程序代码绝对无法看见其他模块内的变量名,除非明确地进行了导入
在Python中,一段程序的作用域完全由程序所处的文件中实际位置决定。作用域绝不会被函数调用或模块导入影响。
重载模块(reload)
与import和from不同的是:
reload是Python中的内置函数,而不是语句
传给reload的是已经存在的模块对象,而不是变量名
reload在Python3.0中位于模块之中,并且必须导入自己
下面是一些细节:
reload会在模块当前命名空间内执行模块文件的新代码
文件中顶层赋值语句会使得变量名换成新值
重载会影响所有使用import读取了模块的客户端
重载只会对以后使用from的客户端造成影响