Python基础——package中的__main__.py和__init__.py简析和用法说明

目录

__init__.py

 Package 中 init 的作用

区分模块

绑定到当前的命名空间

__main__.py文件

if __name__ == '__main__':的作用


├──pkg
│   ├── __init__.py
│   ├── __main__.py
  1. 如果你希望 python 将一个文件夹作为 Package 对待,那么这个文件夹中必须包含一个名为 __init__.py 的文件,即使它是空的。
  2. 如果你需要 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 到其他脚本中是不会被执行的。

  • 11
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值