5.2.5 自定义包

包就是一个至少包含__init__.py文件的文件夹。Python包和Java包的作用是相同的,都是为了实现程序的重用,把实现一个常用功能的代码组合到一个包中,调用包提供的服务从而实现重用。例如,定义一个包parent。在parent包中创建两个子包pack和pack2。pack包中定义一个模块myModule,pack2包中定义一个模块myModule2。最后在包parent中定义一个模块main,调用子包pack和pack2,如图5-2所示。

图5-2 包与模块的树形关系图

【例5-1】通过代码完成自定义包。包pack的__init__.py程序如下所示。

【例5-1.py】


01     if __name__ == '__main__':                    # 判断本模块是否作为主程序运行
02         print ('作为主程序运行')
03     else:
04         print ('pack初始化')

这段代码初始化pack包,这里直接输出一段字符串。当pack包被其他模块调用时,将输出“pack初始化”。包pack的myModule模块如下所示。


01     def func():                                   # 定义func函数
02         print ("pack.myModule.func()")
03
04     if __name__ == '__main__':                    # 判断本模块是否作为主程序运行
05         print ('myModule作为主程序运行')
06     else:
07         print ('myModule被另一个模块调用')

当pack2包被其他模块调用时,将首先执行__init__.py文件。pack2包的__init__.py程序如下。


01     if __name__ == '__main__':
02         print ('作为主程序运行')
03     else:
04         print ('pack2初始化')

包pack2的myModule2模块如下。


01     def func2():                                   # 定义func2函数
02         print ("pack2.myModule2.func()")
03
04     if __name__ == '__main__':                    # 判断本模块是否作为主程序运行
05         print ('myModule2作为主程序运行')
06     else:
07         print ('myModule2被另一个模块调用')

下面的main模块调用了pack、pack2包中的函数。


01     from pack import myModule
02     from pack2 import myModule2
03
04     myModule.func()
05     myModule2.func2()

【代码说明】

·第1行代码从pack包中导入myModule模块,myModule模块被main模块调用,因此输出字符串“myModule被另一个模块调用”。输出结果如下。


pack初始化
myModule被另一个模块调用

·第2行代码从pack2包中导入myModule2模块。输出结果如下。


pack2初始化
myModule2被另一个模块调用

·第4行代码调用myModule模块的函数func()。输出结果如下。


pack.myModule.func()

·第5行代码调用myModule2模块的函数func2()。输出结果如下。


pack2.myModule2.func()

__init__.py也可以用于提供当前包的模块列表。例如,在pack包的__init__.py文件前面添加一行代码。


__all__ = ["myModule"]

__all__用于记录当前pack包所包含的模块。其中方括号中的内容是模块名的列表,如果模块数量超过2两个,使用逗号分开。同理,在pack2包也添加一行类似的代码。


__all__ = ["myModule2"]

这样就可以在main模块中一次导入pack、pack2包中所有的模块。修改后的main模块如下。


01     from pack import *
02     from pack2 import *
03
04     myModule.func()
05     myModule2.func2()

【代码说明】

·第1行代码,首先执行pack包的__init__.py文件,然后在__all__属性中查找pack包含有的模块。如果pack包的__init__.py文件不使用__all__属性记录模块名,main模块调用时将不能识别myModule模块。Python将提示如下错误。


NameError: name 'myModule' is not defined

·第2行代码与第1行代码的作用相同。