用于导入模块时,Python上__init__中__all__的行为

我有一个以下形式的python包:

package
??? __init__.py
??? module_1.py
??? module_2.py
package
??? __init__.py
??? module_1.py
??? module_2.py
package
??? __init__.py
??? module_1.py
??? module_2.
__all__ = ["module_1", "module_2"]

py

package
??? __init__.py
??? module_1.py
??? module_2.
__all__ = ["module_1", "module_2"]

在 __init__.py 里面我有:

Module_1 是:

Module_2 是:

从文档中

__all__ = ["foo"]
def foo(): pass

我认为以下代码将导入fooBar

但是,当

__all__ = ["Bar"]
class Bar: pass

我运行pk.foo()它时会引发错误:(AttributeError: module 'package' has no attribute 'foo'对于 Bar 也是如此)。

感谢这个答案,我知道要获得所需的行为,我可以将 __init__.py 更改为:

以上工作

import package as pk

但是,我不明白 文档。线路:

如果一个包的 __init__.py 代码定义了一个名为 __all__ 的列表,它被认为是遇到 from package import * 时应该导入的模块名称列表

听起来像我原来的 __init__.py 应该工作(那个__all__ = ["module_1", "module_2"])。也就是说,该行import package as pk应已导入模块 module_1module_2,这反过来又化妆fooBar使用。

我错过了什么?

编辑:

我也试过完全使用文档中提到的内容。也就是说,使用from package import *, 然后尝试使用package.foo()foo(),但都没有奏效。

第一个,package.foo(),抛出错误NameError: 'package' is not defined.。第二个,foo(),抛出错误NameError: 'foo' is not defined.

一个工作示例看起来如何?.. __init__.py 的形式为 __all__ = ["module_1", "module_2"]。

回答

我将尝试总结从对我的问题、文档、我自己的测试和这篇文章的评论中获得的知识。

1)__all____init__和 模块上表现不同

1.1) 在一个模块内

_所有_ is within a _module_, it determines what objects are made available when runningfrom 模块导入 *`。

鉴于此包结构:

并给出以下代码module_1

运行from package.module_1 import *将使foo可用但不可用baz

此外,foo可以使用 using 调用foo(),即不需要引用模块。

1.2)内__init__(我原来的问题)

__all__在 内时__init__

它被认为是列表模块名称应导入时,从包导入*遇到的。

运行from package import *将有两个效果:

  1. 模块的脚本__all__将被运行(它们被导入)。
  2. 这些模块在命名空间中可用。

这意味着如果__init__是以下形式:

然后,运

__all__ = ["foo"]
def foo(): pass
def baz(): pass

from package import *将运行的脚本module_1module_2以及使这两个模块提供。所以,现在,foo里面的函数module_1可以调用 asmodule_1.foo() 而不是 package.module_1.foo()

但是,如果这是意图,那么使用from package.module_1 import foo可能会更好。因为它foo可以作为foo().

2)from package import *不一样import package

运行from package import *1.2)中提到的效果。但是,这不适用于运行import package:即module_1.foo()在这种情况下不起作用。

3) 替代方法 __init__

(以下是基于此职位)正如我在问题中提到,有一种替代方法__init__,其中的对象,你要提供当用户呼叫from package import *直接导入__init__

例如,__init__可以包含以下代码:

然后,当用户调用from package import *模块 1 和 2 中的对象时,命名空间上的对象将可用。

如果module_11.1),则foo可以在不引用模块的情况下调用该函数。即foo()。但是,这同样不适用于baz.

2) 中所述from package import *与 不同import packageimport package在这种情况下调用(使用 this __init__),使 foo 通过 可用package.foo()不仅仅是foo()。同样import package as pk使 foo 可用作pk.foo().

这种方法可能比1.2) 的方法更可取,在1.2)foo可以通过module_1.foo().


以上是用于导入模块时,Python上__init__中__all__的行为的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>