gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 11:29:56 25 4
gpt4 key购买 nike

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

package
├── __init__.py
├── module_1.py
└── module_2.py
在 __init__.py 里面我有:
__all__ = ["module_1", "module_2"]
Module_1 是:
__all__ = ["foo"]
def foo(): pass
Module_2 是:
__all__ = ["Bar"]
class Bar: pass
来自 documentation我以为下面的代码会导入 fooBar :
import package as pk
但是,当我运行 pk.foo() 时它抛出一个错误: AttributeError: module 'package' has no attribute 'foo' (酒吧相同)。
感谢 this回答,我知道要获得所需的行为,我可以将 __init__.py 更改为:
from .module_1 import *
from .module_2 import *
以上工作。
然而, 我不明白 documentation .线路:

if a package’s __init__.py code defines a list named __all__, it is taken to be the list of module names that should be imported when from package import * is encountered


听起来像我原来的 __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"]。

最佳答案

我将尝试总结从对我的问题的评论中获得的知识,documentation 、我自己的测试和 this邮政。
1) __all____init__ 上的行为有所不同和模块
1.1) 在一个模块内
_所有_ is within a _module_, it determines what objects are made available when running从模块导入 *`。
鉴于此包结构:

package
├── __init__.py
├── module_1.py
└── module_2.py
并给出以下代码 module_1 :
__all__ = ["foo"]
def foo(): pass
def baz(): pass
运行 from package.module_1 import *将使 foo 可用 但不是 baz .
此外, foo 然后可以使用 foo() 调用,即不需要引用模块。
1.2) 内 __init__ (我原来的问题)
__all____init__ 内,

it is taken to be the list of module names that should be imported when from package import * is encountered.


运行 from package import *然后会有两个效果:
  • __all__中模块的脚本将运行(它们是导入的)。
  • 这些模块在命名空间中可用。

  • 这意味着如果 __init__是以下形式:
    __all__ = ["module_1", "module_2"]
    然后,运行 from package import *将运行 module_1 的脚本和 module_2使两个模块都可用 .所以,现在,函数 foomodule_1可以称为 module_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__的替代方法
    (以下基于 this 帖子)正如我在我的问题中提到的,有一种替代方法 __init__ ,其中您希望在用户调用 from package import * 时可用的对象是 直接导入__init__ .
    例如, __init__可能包含以下代码:
    from .module_1 import *
    from .module_2 import *
    然后,当用户拨打 from package import *来自模块 1 和 2 的对象将在命名空间中可用。
    module_1 1.1) ,然后函数 foo可以在不引用模块的情况下调用。即 foo() .但是,同样的方法不适用于 baz .
    中所述2) , from package import *import package 不同.调用 import package在这种情况下(使用此 __init__),通过 package.foo() 使 foo 可用, 而不是 只是 foo() .同样 import package as pk使 foo 可用为 pk.foo() .
    这种方法可能优于 1.2) ,其中 foo可通过 module_1.foo() 获得.

    关于python - 用于导入模块时,Python 上 __init__ 中 __all__ 的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67142515/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com