python模块和包:最全面介绍(二)
import语句
最简单的import语句当属import <module_name>。这样import后,并不意味着module中的内容可以直接被调用了。每个模块都有自己的私有符号表,private symbol table,这张表对于module中被定义的对象来说,是张全局性的符号表。即module会单独创建一个命名空间。
使用import,仅仅是将模块放入调用者的symbol table,模块中的对象,仍然在模块的private symbol table中。调用者只有通过dot notation才能di调用模块中的对象。>>> import mod>>> mod<module mod from C:\\Users\\Steven\\Documents\\Python\\doc\\mod.py>>>> mod.sIf Comrade Napoleon says it, it must be right.>>> mod.foo(quux)arg = quuxfrom
因为这种形式的import可以将任何对象直接导入调用者的符号表,之前存在的具有同样名称的对象会被覆盖掉。
>>> a = [foo, bar, baz]>>> a[foo, bar, baz]>>> from mod import a>>> a[100, 200, 300]我们也可以一下子把一个模块里的所有对象都一下子导入,用from <module_name> import *,这会把模模块中所有的对象都导入到本地的符号表中,当然那些以下划线开头的对象不会被导入。
把所有对象都一下子导入到当前的代码中,在大型的生产代码编写实践中,我们并不鼓励。这有点危险,你把这些名称一下子导入到本地的符号表。除非你对这些被导入的对象非常熟悉,而且,很确定他们不会引起冲突。当然这个语句在你测试的时候会非常顺手,尤其是你利用交互式编译器来测试,或者搞一些发现式的探索的时候,这会省去一些打字的时间。
还可以把导入的包重命名:from <module_name> import <name> as <alt_name>,或者import <module_name> as <alt_name>。
这种一下子把所有对象都导入的语法,python3不允许。
dir()函数内置函数dir()返回命名空间中已经被定义的名称,会返回一个列表,这个函数会返回当前局部符号表中的名称,按字母顺序排序。这个函数可以用来查看import语句往当前命名空间里添加了什么变量。
如果给dir()函数一个参数,这个参数代表模块名称,则会返回这个模块中的所有被定义的名称。
将模块当做脚本执行我们在《Python模块和包:最全面介绍(一)》中提到的mod.py,可以被当做一个脚本执行。
s = "If Comrade Napoleon says it, it must be right."a = [100, 200, 300]def foo(arg): print(farg = {arg})class Foo: passprint(s)print(a)foo(quux)x = Foo()print(x)如果我们想在执行它的时候输出一些东西,我们可以加上一些print语句。
C:\Users\john\Documents>python mod.pyIf Comrade Napoleon says it, it must be right.[100, 200, 300]arg = quux<__main__.Foo object at 0x02F101D0>但现在如果把它当做一个模块来导入,导入的时候也会打印出这些信息。所以现在我们想实现的是当一个模块,被导入的时候不应该输出信息,当它被当作脚本执行的时候可以输出信息。
当一个py文件被当做模块来导入的时候, Python会把__name__变量的值设置为这个模块的名称,如果一个py文件被当做一个独立的脚本来执行, Python会把__name__变量的值设置为__main__,我们可以使用这个特性来区分一个py文件,到底是被导入还是被当做一个独立的脚本来执行。
s = "If Comrade Napoleon says it, it must be right."a = [100, 200, 300]def foo(arg): print(farg = {arg})class Foo: passif (__name__ == __main__): print(Executing as standalone script) print(s) print(a) foo(quux) x = Foo() print(x)程序员在编写模块的时候经常会设计这样一个功能,使模块可以作为一个独立的脚本来执行,以便测试一些这个脚本所含的功能,这叫单元测试。
比如我们可以设计一个阶乘函数:
def fact(n): return 1 if n == 1 else n * fact(n-1)if (__name__ == __main__): import sys if len(sys.argv) > 1: print(fact(int(sys.argv[1])))if (__name__ == __main__): 后面的语句,起到在这个脚本在命令行被执行的时候,传递参数的作用。