Fork me on GitHub

python包

包的每一层下面都有一个名为__init__.py的模块,该模块可以为空,用于标识python包

以下为调用方式 从test包下调用a文件中调用a方法

from test.a import a

目录结构如下 

test目录下__init__.py内容为空

test目录下a.py内容

def a():
    print('a')

 test目录同级目录中test.py内容

from test.a import a

a()

执行 python.exe test.py 结果如下: 

结果没有问题,程序运行也正常。

如果在test文件下有10个xxx.py文件,还要写10个 from test import a,xxx,或者写10个 from test import a 这样的语句,这太繁琐。

或许使用 from test import * 这样的语句也不错

test目录下__init__.py内容为空

test目录下a.py内容

def a():
    print('a')

 dir目录下test.py内容

from test import *

a.a()

执行 python.exe test.py 结果如下: 

错误提示:a 这个名字没有定义

为什么行不通呢?

python不建议使用 from test import * 这种方式编程,但在开发测试中,这种方式极为方便。

但,python 已经解决了这个问题,解决的途径就是__init__.py 这个标识文件

说明,python命名空间

在python中有可以使用__all__来显式指定 import * 中 导入的成员,未被指定的不能被导入,这样可以保护模块安全

test目录下__init__.py内容:

__all__ = ['a']

 

test目录下a.py内容

def a():
    print('a')

 dir目录下test.py内容

from test import *

a.a()

执行 python.exe test.py 结果如下: 

定义 all 需要注意的地方
  如上所述,__all__ 应该是 list 类型的
  不应该动态生成 __all__,比如使用列表解析式。__all__ 的作用就是定义公开接口,如果不以字面量的形式显式写出来,就失去意义了。
  即使有了 __all__ 也不应该在非临时代码中使用 from xxx import * 语法,或者用元编程手段模拟 Ruby 的自动 import。Python 不像 Ruby,没有 Module 这种成员,模块就是命名空间隔离的执行者。如果打破了这一层,而且引入诸多动态因素,生产环境跑的代码就充满了不确定性,调试也会非常困难。
  按照 PEP8 建议的风格,__all__ 应该写在所有 import 语句下面,和函数、常量等模块成员定义的上面。

如果一个模块需要暴露的接口改动频繁,__all__ 可以这样定义:

__all__ = [
    "a",
    "b",
    "c",
]

 参考网址:

https://blog.csdn.net/qq_32166627/article/details/59481503

https://blog.csdn.net/hang916/article/details/79474821

 

posted on 2018-11-05 13:08  anyux  阅读(154)  评论(0)    收藏  举报