Python中级精华模块和包
模块和包概念:
模块:每个独立的py文件
包:描述模块组织构成
例如:#包: package1/ __init__.py sub_package1/ __init__.py test.py text.py sub_package2/ __init__.py png.py jpg.py
然后如何使用呢?import package1.sub_package1.test from package1.sub_package1 import text import package1.sub_package2.jpg as jpg
__init__.py存在的目的就是为了包含可选的初始化代码,当遇到软件保重不同层次的模块时会触发运行,例如,比如写下import package1 时,文件package1/ __ init __ .py就会生成package1命名空间中的内容。
__ init __.py文件可以留空,但是在某些情况下可以用init来自动加载子模块,示例如下:#package1/sub_package2/__init__.py from . import jpg from . import png
有了这个文件,用户就可以使用单独的一句 import package.sub_package2来完成导入jpg和png了。对所有符号的导入进行精确控制
示例:def aFunc(): pass def bFunc(): pass __bash = False # 这样做,可以避免在使用 from … import *这个导入方式时将__bash也导入到文件中 #(__bash前边提过,这种写法并不希望暴露给其他文件) __all__ = ["aFunc","bFunc"]#仅仅为导入时自动补全aFunc和bFunc,__bash不会被提示。 # 注意:如果__all__为空列表时,将没有任何符号被导出,如果__all__中包含了未定义的名称,则会由import抛出AttributeError异常。
用相对名称进行导入包中的子模块mypackage/ __init__.py A/ __init__.py soam.py grok.py B/ __init__.py bar.py
如上,我们希望在soam.py中导入同目录下的grok文件:from . import grok
如果我们希望在soam.py中导入B中的bar.py,则要如下导入:from ..B import bar
名词解释:
相对名称:
. :当前目录
. . :上一级目录
也可以通过绝对名称来导入:#在soam.py中: from mypackage.B import bar from mypackage.A import grok
使用绝对名称导入有一个较大的缺陷,这使得包结构及代码变得异常脆弱,因为如果更改了包名或者模块名,将导致异常,而在大型的文件系统中,这个硬编码到源码中的技术实际上并不可取。值得一提的是,这种句点操作并不是哪里都可以用的,第一、句点返回上一级目录不得超出包外(例如:from …B… import …之类的操作),第二点、模块必须是在合适的包结构内才可以使用句点符号(单独的模块这样导入会使得程序崩溃),三、当包(soam.py)的某个部分是以脚本形式运行的也不行(但是如果使用-m来运行(python3 -m xxx.py)上边的脚本,就可以使用相对名称了)