本文共 4189 字,大约阅读时间需要 13 分钟。
Python在处理功能复用和功能颗粒度划分时采用了类、模块、包的结构。这种处理跟C++中的类和名字空间类似,但更接近于Java所采用的概念。
类的概念在许多语言中出现,很容易理解。它将数据和操作进行封装,以便将来的复用。
模块,在Python可理解为对应于一个文件。在创建了一个脚本文件后,定义了某些函数和变量。你在其他需要这些功能的文件中,导入这模块,就可重用这些函数和变量。一般用module_name.fun_name,和module_name.var_name进行使用。这样的语义用法使模块看起来很像类或者名字空间,可将module_name 理解为名字限定符。模块名就是文件名去掉.py后缀。下面演示了一个简单的例子:
#moduel1.pydef say(word): print word#caller.pyimport module1print __name__print module1.__name__module1.say('hello')
$ python caller.py__main__module1hello
例子中演示了从文件中调用模块的方法。这里还展示了一个有趣的模块属性__name__,它的值由Python解释器设定。如果脚本文件是作为主程序调用,其值就设为__main__,如果是作为模块被其他文件导入,它的值就是其文件名。这个属性非常有用,常可用来进行模块内置测试使用,你会经常在一些地方看到类似于下面的写法,这些语句只在作为主程序调用时才被执行。
if __name__ == '__main__': app = wxapp(0) app.MainLoop()
上面的例子中,当module1被导入后,python解释器就在当前目录下寻找module1.py的文件,然后再从环境变量PYTHONPATH寻找,如果这环境变量没有设定,也不要紧,解释器还会在安装预先设定的的一些目录寻找。这就是在导入下面这些标准模块,一切美好事情能发生的原因。
import osimport sysimport threading...
这些搜索目录可在运行时动态改变,比如将module1.py不放在当前目录,而放在一个冷僻的角落里。这里你就需要通过某种途径,如sys.path,来告知Python了。sys.path返回的是模块搜索列表,通过前后的输出对比和代码,应能理悟到如何增加新路径的方法了吧。非常简单,就是使用list的append()或insert()增加新的目录。
#module2.pyimport sysimport osprint sys.pathworkpath = os.path.dirname(os.path.abspath(sys.argv[0]))sys.path.insert(0, os.path.join(workpath, 'modules'))print sys.path
$ python module2.py['e:\\Project\\Python', 'C:\\WINDOWS\\system32\\python25.zip', ...]['e:\\Project\\Python\\modules', 'e:\\Project\\Python', 'C:\\WINDOWS\\system32\\python25.zip', ...]
模块能像包含函数定义一样,可包含一些可执行语句。这些可执行语句通常用来进行模块的初始化工作。这些语句只在模块第一次被导入时被执行。这非常重要,有些人以为这些语句会多次导入多次执行,其实不然。
模块在被导入执行时,python解释器为加快程序的启动速度,会在与模块文件同一目录下生成.pyc文件。我们知道python是解释性的脚本语言,而.pyc是经过编译后的字节码,这一工作会自动完成,而无需程序员手动执行。
在创建许许多多模块后,我们可能希望将某些功能相近的文件组织在同一文件夹下,这里就需要运用包的概念了。包对应于文件夹,使用包的方式跟模块也类似,唯一需要注意的是,当文件夹当作包使用时,文件夹需要包含__init__.py文件,主要是为了避免将文件夹名当作普通的字符串。__init__.py的内容可以为空,一般用来进行包的某些初始化工作或者设置__all__值,__all__是在from package-name import *这语句使用的,全部导出定义过的模块。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------另一篇
Python中的Module是比较重要的概念。常见的情况是,事先写好一个.py文件,在另一个文件中需要import时,将事先写好的.py文件拷贝 到当前目录,或者是在sys.path中增加事先写好的.py文件所在的目录,然后import。这样的做法,对于少数文件是可行的,但如果程序数目很 多,层级很复杂,就很吃力了。
有没有办法,像Java的Package一样,将多个.py文件组织起来,以便在外部统一调用,和在内部互相调用呢?答案是有的。 要弄明白这个问题,首先要知道,Python在执行import语句时,到底进行了什么操作,按照Python的文档,它执行了如下操作: 第1步,创建一个新的,空的module对象(它可能包含多个module); 第2步,把这个module对象插入sys.module中 第3步,装载module的代码(如果需要,首先必须编译) 第4步,执行新的module中对应的代码。 在执行第3步时,首先要找到module程序所在的位置,其原理为: 如 果需要导入的module的名字是m1,则解释器必须找到m1.py,它首先在当前目录查找,然后是在环境变量PYTHONPATH中查找。 PYTHONPATH可以视为系统的PATH变量一类的东西,其中包含若干个目录。如果PYTHONPATH没有设定,或者找不到m1.py,则继续搜索 与Python的安装设置相关的默认路径,在Unix下,通常是/usr/local/lib/python。 事实上,搜索的顺序是:当前路径 (以及从当前目录指定的sys.path),然后是PYTHONPATH,然后是Python的安装设置相关的默认路径。正因为存在这样的顺序,如果当前 路径或PYTHONPATH中存在与标准module同样的module,则会覆盖标准module。也就是说,如果当前目录下存在xml.py,那么执 行import xml时,导入的是当前目录下的module,而不是系统标准的xml。 了解了这些,我们就可以先构建一个package,以普通module的方式导入,就可以直接访问此package中的各个module了。 Python中的package定义很简单,其层次结构与程序所在目录的层次结构相同,这一点与Java类似,唯一不同的地方在于,Python中的package必须包含一个__init__.py的文件。 例如,我们可以这样组织一个package: package1/ __init__.py subPack1/ __init__.py module_11.py module_12.py module_13.py subPack2/ __init__.py module_21.py module_22.py …… __init__.py可以为空,只要它存在,就表明此目录应被作为一个package处理。当然,__init__.py中也可以设置相应的内容,下文详细介绍。 好了,现在我们在module_11.py中定义一个函数: def funA(): print "funcA in module_11" return 在顶层目录(也就是package1所在的目录,当然也参考上面的介绍,将package1放在解释器能够搜索到的地方)运行Python: >>>from package1.subPack1.module_11 import funcA >>>funcA() funcA in module_11 这样,我们就按照package的层次关系,正确调用了module_11中的函数。 细心的用户会发现,有时在import语句中会出现通配符*,导入某个module中的所有元素,这是怎么实现的呢? 答案就在__init__.py中。我们在subPack1的__init__.py文件中写 __all__ = ['module_13', 'module_12'] 然后进入Python >>>from package1.subPack1 import * >>>module_11.funcA() Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named module_11 也就是说,以*导入时,package内的module是受__init__.py限制的。 好了,最后来看看,如何在package内部互相调用。 如果希望调用同一个package中的module,则直接import即可。也就是说,在module_12.py中,可以直接使用 import module_11 如果不在同一个package中,例如我们希望在module_21.py中调用module_11.py中的FuncA,则应该这样: from package1.subPack1.module_11 import funcA 当然,在Python 2.5中,有更简单的办法: from .. subPack1.module_11 import funcA转载地址:http://ygwub.baihongyu.com/