首页 > 编程语言 > 详细

Python:__init__.py文件和、__all__、import、__name__、__doc__

时间:2020-05-04 20:12:39      阅读:71      评论:0      收藏:0      [点我收藏+]

有时候,很容易忽略一些看上去不起眼的小细节,可能人总是有那么点理所当然的想法。

就像init.py文件,是不是感觉像个熟悉的陌生人?~~~

这里来浅析一下一些基础概念(都是左右各双下划线)。

1. __init__.py 文件:这个文件,就像一个标识符一样,用来表明一个文件夹是python包还是一般文件夹,如果文件夹中存在该文件,就是python包;可以试试pycharm直接建立package,就会发现刚建完就已经存在__init__.py文件了。

这个文件用处:

用处一:当用于import对象时,可以识别出哪些是可以导入的包,哪些只是一般文件夹;

用处二:可以在其中导入需要的对象,每次导入package的时候会自动执行__init__.py,避免麻烦;但最好不要在这里写自己的模块,该文件越简单越好;

用处三:__all__参数,可以用于指定 from package import * 时,导入的包是哪些,不需要的包可以先不导入。

注意:该文件可以为空,即不做操作,但是package必须要有这个文件。

2. import:用于导入包、函数、变量、类等;那么import干了些啥?(sys.path是可以修改的,且从package包导入模块需要用 from package import ... 形式

技术分享图片

3. __name__:用于判断当前模块是不是主程序文件(主执行),也就是查看 __name__ 的值是否为 ‘__main__‘ ,如果则该程序属于主程序文件,如果不是则显示该文件的文件名;

4. __doc__:模块的注释文本,例如函数或者类的说明,用 ‘‘‘...‘‘‘ 三引号形式包围;

5. 示例说明

(1)首先文件夹和文件如下:可见my_init是一个python包,package_test也是一个包,my_init_2是一个普通文件夹。

技术分享图片

(2)首先两个 __init__.py都为空,此时import模块的操作如下:

## import_test.py 内容

class BBB():
    def __init__(self, kk):
        self.kk = kk
        print(self.kk)
    
    def gogogo(self):
        print(---test class with import---)
        
def ss_B():
    print(---------------- this is the imported *.py file --------------)

def tt_B():
    print(this is also from imported file)

print(it is very bad)
print(__name__)

if __name__ == "__main__":
    print(__name__)
    ss_B()
  • main_test.py导入import_test模块 —— 两个py文件在同一目录下
# 直接导入,main_test.py

import import_test as it
it.ss_B()
print(__name__)

技术分享图片

很明显,前两个结果来自导入import_test时,自动执行了该模块 import_test中的内容(输出的结果1和结果2);而为啥没继续执行下面的 if __name__=‘__main__‘ 里面的内容,那是因为此时__name__的值为:import_test(输出的结果2),并不是__main__,所以不会执行。

然后,结果3调用了import_test模块内的函数,结果4返回__main__,表明当前模块(main_test.py)属于主程序。

  • main_test.py导入import_test模块,同一目录,也可以如下
# main_test.py

from
import_test import ss_B #可以直接通过py文件导入函数,模块可以通过 from module_name import func 或者直接 import module_name;但是package要通过from package_name import module_name 或者 import package_name.module_name def ss(): print(---------------- this is the main *.py file --------------) if __name__ == "__main__": print(__name__) #用于判断主程序是当前程序还是其他程序 ss() ss_B()

此时不能用:from my_init import import_test,为什么呢?因为my_init这个文件不在搜索路径下,但是它的子目录在搜索路径(D:\\Python_workspace\\Felix_test\\test_init\\my_init)下,可以使用sys.path查看:

技术分享图片

如果要是用,需要先将该目录加入搜索路径(它本身的目录为 —— D:\Python_workspace\Felix_test\test_init\my_init),通过绝对地址加入

# main_test.py

import
sys,os sys.path.append(os.path.abspath(rD:\Python_workspace\Felix_test\test_init)) #只有test_init目录下才包含my_init目录 from my_init import import_test

 技术分享图片

  • main_test.py导入package_test包中的模块,main_test和package_test包同一目录
# sub_test.py 内容

def sub_packege_test():
    ‘‘‘testing on the sub_packege_test doc ---‘‘‘
    print(it is a sub-package!)

则,调用时,__doc__表示说明文本(每个对象,例如函数、类、模块都有这个属性):

# main_test.py

from package_test import sub_test     #导入包中的文件
sub_test.sub_packege_test()
print(sub_test.sub_packege_test.__doc__)  #该函数说明

技术分享图片

也可:

from package_test.sub_test import sub_packege_test  #导入包内*.py文件中的函数
sub_packege_test()
  • my_init_2文件夹中的test_1.py可以直接调用test_2.py,同一目录,虽然这个文件夹不是package
# test_2.py 内容
def xx():
    print(-----what happended here-----)
print(xx())  

# ---------------------------------------------------------------------------
# test_1.py 内容 import test_2 as t2 t2.xx() print(it is test_1.py)
  • my_init_2文件夹中的test_2,无法直接import my_init包中的import_test.py模块,需要先添加搜索路径;反之,也可以在my_init包中的模块,import另一个文件夹(my_init_2)中的模块 —— 注意:这可能会失败,因为你import的模块有可能会导入import其他的包,但是这些其他包又不在搜索路径中时,就会报错。
# test_2.py 内容

import os
import sys
sys.path.append(os.path.abspath(rD:\Python_workspace\Felix_test\test_init))  #绝对路径导入包,先将文件夹加入搜索路径,然后导入;相对路径个人感觉不太好用
from my_init import import_test

import_test.ss_B()

def xx():
    print(-----what happended here-----)
print(xx())  

所以,最好不要嵌套太多层来进行import。。。

(3)使用__init__.py方法

  • main_test.py中import package_test中的模块

首先,修改my_init包的package_test中的__init__.py文件如下(使用__all__变量):

__all__ = [sub_test]   #可以只选部分,不用导入过多包

print(this is from __init__ file, sub-package)

然后,import使用:

# sub_test.py 内容
def sub_packege_test():
    ‘‘‘testing on the sub_packege_test doc ---‘‘‘
    print(it is a sub-package!)

#-------------------------------------------------
# main_test.py
from package_test import *
sub_test.sub_packege_test()
print(__name__)
sub_test_2.sub_packege_test_2()

技术分享图片

可见:当使用 from package_test import * 时,读取到的包均属于package_test的 __init__.py中 __all__变量的值,不在该变量值中的包不会读取。

  • 此时,如果__init__.py中没有某个模块,而你又要使用时,可以自己导入
from package_test import sub_test_2
sub_test_2.sub_packege_test_2()

技术分享图片

  • 如果,不使用__all__变量,直接在__init__.py中import需要的包
# package_test中的__init__.py文件内容:

from package_test import sub_test
print(this is from __init__ file, sub-package)

这种情况与直接在需要的地方通过from package import module,来导入模块差不多;只不过如果使用了__init__.py文件,那么就会执行一次__init__.py文件,此时如果该文件里面还有其他代码也会执行。

# main_test.py

from package_test import sub_test
#import sub_test   #直接导入该模块不行
sub_test.sub_packege_test()

 

注意:

1. from module/package import func/module:只是将某模块或者package的一部分导入当前命名空间;

2. import语句中,如果导入的是模块则会执行该模块代码;如果是package,则会执行package包的__init__.py文件;

3. sys.modules 和 sys.path的官方链接、解释:

技术分享图片

4. __init__.py文件越简单越好,也可以为空。

 

#

参考:

https://blog.csdn.net/fitzzhang/article/details/78988155

https://www.jianshu.com/p/dacbed54d063

https://www.runoob.com/python/python-modules.html

https://blog.csdn.net/weixin_38256474/article/details/81228492

https://www.cnblogs.com/byronsh/p/10745292.html

Python:__init__.py文件和、__all__、import、__name__、__doc__

原文:https://www.cnblogs.com/qi-yuan-008/p/12827918.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!