目录
- ├──pkg
- │ ├── __init__.py
- │ ├── __main__.py
如果你希望 python 将一个文件夹作为 Package 对待,那么这个文件夹中必须包含一个名为 __init__.py 的文件,即使它是空的。
如果你需要 python 将一个文件夹作为 Package 执行,那么这个文件夹中必须包含一个名为 __main__.py 的文件。
在实际中,可以将pkg作为一个文件夹执行:python pkg
也可以将pkg作为一个Package执行:python -m pkg
__init__.py
__init__.py是编辑器用来标识package包的
如果你仅仅只是编写一个python程序,那么这个__init__.py可有可无,但是你要是想写一个包想写一个模块,想让这个包在别的程序中可以调用,那么这个文件一定要有,里面可以空着什么都不写,但是一定要有。
例子:
1. 现在package文件TestPy下有三个python文件,分别为Test.py、Test2.py、__init__.py
Test.py
- def A():
- print("A()")
- def B():
- print("B()")
Test2.py
- from TestPy import *
- A()
- B()
__init__.py
- from TestPy.Test import *
- __all__ = ['A']
2. 使用一个包或者模块,有两种操作,精准导入和模糊导入
2.1. 精准导入
示例如下:
from TestPy.Test import A
这样只能使用Test.A(),用什么就调用什么,大大增加了速度。
思考问题:
那么我们需要导入大量的方法,怎么办?一个一个导?
2.2. 模糊导入
示例如下:
from TestPy.Test import *
使用 from package import * 的时候就把这个列表中的所有名字作为包内容导入。
作为包的作者,可别忘了在更新包之后保证 __all__ 也更新了啊。
以下实例在 file:sounds/effects/__init__.py 中包含如下代码:
__all__ = ["echo", "surround", "reverse"]
这表示当你使用from sound.effects import *这种用法时,你只会导入包里面这三个子模块。
如果 __all__ 真的没有定义,那么使用from sound.effects import *这种语法的时候,就不会导入包 sound.effects 里的任何子模块。他只是把包sound.effects和它里面定义的所有内容导入进来(可能运行__init__.py里定义的初始化代码)。
通常我们并不主张使用 * 这种方法来导入模块,因为这种方法经常会导致代码的可读性降低。不过这样倒的确是可以省去不少敲键的功夫,而且一些模块都设计成了只能通过特定的方法导入。
记住,使用 from Package import specific_submodule 这种方法永远不会有错。事实上,这也是推荐的方法。除非是你要导入的子模块有可能和其他包的子模块重名。
3. __init__.py里的 __all__
在 __all__中可以声明定义允许用户可以调用的方法,以在 __all__ 中限定用户调用的范围
入示例代码所示,只允许调用Test的A()方法
- from TestPy.Test import *
- __all__ = ['A']
如果强行调用Test的B()方法会报错,如截图所示
Package 中 init 的作用
区分模块
在Python 中,一个 py文件,对应的就是一个模块。
在 my_package包 中创建三个子包 package_one、package_two、package_three
在编写的python程序中,不能同时导入两个同名的模块,而我们的程序又要用到这两个 py文件 里的内容,那么可以采用将这两个 py文件 放入两个不同的包下,通过导入不同包的方式进行区分,导入这两个不同的模块。
在 package_one 的 my_moudel 文件中定义类test1
- class test1():
- print('*' * 10)
- if __name__ == '__main__':
- pass
在 package_two 的 my_moudel 文件中定义类test2
- class test2():
- print('*' * 20)
- if __name__ == '__main__':
- pass
在 package_three 的 my_moudel 文件中定义类test3
- class test3():
- print('*' * 30)
- if __name__ == '__main__':
- pass
新建一个 my_print.py 文件,导入3个 my_moudel 模块
- import my_package.package_one.my_moudel
- import my_package.package_two.my_moudel
- import my_package.package_three.my_moudel
- f1 = my_package.package_one.my_moudel.test1
- f2 = my_package.package_two.my_moudel.test2
- f3 = my_package.package_three.my_moudel.test3
- # 运行 my_print.py文件,结果为:
- **********
- ********************
- ******************************
绑定到当前的命名空间
分别在子包的 init 文件中写入以下内容:
package_one
print('这是子包 one 的 init')
package_two
print('这是子包 two 的 init')
在父亲包 my_package 中写入以下内容:
print('这是父亲包 的 init')
新建一个 test.py 文件(可建在my_package 包外面),进行导包操作
只导入父模块 my_package
- import my_package
- # 运行test.py文件,结果为:
- # 这是父亲包 的 init
总结:只导入父模块的时候只会执行父模块中的 init
单独导入子模块 package_one
- import my_package.package_one
- # 运行test.py文件,结果为:
- # 这是父亲包 的 init
- # 这是子包 three 的 init
单独导入package_two
- import my_package.package_two
- # 运行test.py文件,结果为:
- # 这是父亲包 的 init
- # 这是子包 two 的 init
单独导入package_three
- import my_package.package_three
- # 运行test.py文件,结果为:
- # 这是父亲包 的 init
- # 这是子包 three 的 init
三个包均导入
- import my_package.package_one
- import my_package.package_two
- import my_package.package_three
- # 运行test.py文件,结果为:
- # 这是父亲包 的 init
- # 这是子包 one 的 init
- # 这是子包 two 的 init
- # 这是子包 three 的 init
总结:导入父模块中的子模块的时候,优先执行父模块中的 init ,再执行指定模块中的 init
也就是说,当我们去 import 一个 Package 的时候,它会隐性的去执行 __init__.py ,
而在 __init__.py 中定义的对象,会被绑定到当前的命名空间里面来。
有时候我们会这样去导入一个包下的所有模块:
- from my_package import *
- # 运行test.py文件,结果为:
- # 这是父亲包 的 init
但这个时候却并没有将相关的子模块导入进来,如果想采用这种导包的方式,也将子模块导入进来,或者导入某些特定的子模块进来,可采用对 父亲包的 init 文件进行编辑:
- print('这是父亲包 的 init')
- __all__ = ['package_one','package_three']
- # 这里的 __all__ 相当于导入 [] 里面定义的模块
此时再运行 test.py 文件
- from my_package import *
- # 运行test.py文件,结果为:
- # 这是父亲包 的 init
- # 这是子包 one 的 init
- # 这是子包 three 的 init
__main__.py文件
当我们创建一个Python包时,需有一个__init__.py文件,它是用来标识Python包的,用来与普通文件夹做区分;
我们同样可以在一个Python包中创建一个__main__.py文件,类似于if __name__ == "__main__",模块的__name__.py文件在通过命令行输入的时候作用等同于if __name__ == "__main__";
在命令行直接输入python -m package_name 就可以执行__main__.py文件
if __name__ == '__main__':的作用
一个python文件通常有两种使用方法,第一是作为脚本直接执行,第二是 import 到其他的 python 脚本中被调用(模块重用)执行。因此 if __name__ == 'main': 的作用就是控制这两种情况执行代码的过程,在 if __name__ == 'main': 下的代码只有在第一种情况下(即文件作为脚本直接执行)才会被执行,而 import 到其他脚本中是不会被执行的。