gpt4 book ai didi

python - import 语句如何修改模块的符号表?

转载 作者:行者123 更新时间:2023-12-01 00:50:55 26 4
gpt4 key购买 nike

我有以下模块:

foo/
__init__.py
random.py

random.py只是一个空文件,并且 __init__.py包含这个:

import random

def print_random():
import foo.random
print(random.random())

当我使用 python -c 'import foo; foo.print_random()' 调用上述函数时,我得到AttributeError: module 'foo.random' has no attribute 'random' .

看来print_random()中的导入语句已将对内置模块的引用替换为对 foo.random 的引用。谁能向我解释为什么它没有在上述表中添加新记录?我在哪里可以阅读更多相关内容?有没有推荐的做法可以避免这种情况?

更新#1

我在 Python 2.7 和 Python 3.5 中都遇到了同样的错误。我注意到的唯一区别是 Python 2 的措辞略有不同: AttributeError: 'module' object has no attribute 'random' .

sys.modules['random']print_random()指的是内置随机模块,但是 globals()['random']指的是foo/random.py .

import foo.random不必位于print_random()中。可以将其从那里删除并添加到用于运行脚本的命令中(例如 python -c 'import foo; import foo.random; foo.print_random()'),这将产生相同的结果。

最佳答案

这里有两种机制在起作用:

一方面,当执行import foo.random语句时,我们通常期望名称foo将绑定(bind)在本地上下文中,并且foo.random 将根据 import 语句的 docs. 作为 foo 的成员使用。

另一方面,“当使用任何机制加载子模块时[...],每个子模块 doc 都会将绑定(bind)放置在父模块的命名空间中到子模块对象” 。

__init__.py 文件的特殊情况下,这意味着 foo.random 既可用作名称 random 也可用作绑定(bind)到 foo 的对象的 random 成员,因为在 __init__.py 文件中,我们直接在父模块的上下文中工作(即我们在 foo 上下文中工作,而不是在 foo.__init__ 上下文中工作)。

最好的解决方案是如果可以避免的话,不要在 __init__ 包中编写代码,而只是使用它来公开名称、初始化记录器等。始终为以下内容创建一个包也是一个很好的做法为了表现力而相对于父包公开的模块,尽管它不能解决这个问题。

总之,如果您想公开一个 foo.random 包,同时拥有一个包含上述内容的 foo.print_random 函数,我建议使用以下布局:

foo/
__init__.py
print_random.py
random/
__init__.py

foo/__init__.py

from foo.print_random import print_random

foo/print_random.py

import random

def print_random():
import foo.random
print(random.random())

关于python - import 语句如何修改模块的符号表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56578706/

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