导入是否以某种方式超越了模块名称空间?

Do imports somehow transcend module namespaces?

我有一个模块(比如模块 A),其功能之一是 returns 一个 BeautifulSoup 对象。我正在编写第二个模块(模块 B),它调用此函数并存储 BeautifulSoup 对象。我很困惑如何在模块 B 中模块 A 返回的对象上调用 BeautifulSoup 函数,而模块 B 不从 bs4 导入任何内容,或者必须通过模块 A 访问那些 BS4 函数。导入基本上是 module_a 及其在包中的所有导入,因此 BeautifulSoup class 对 module_b?

可见

module_a.py

from bs4 import BeautifulSoup
def function():
    some_xml = "<name>Namespaces are strange.</name>"
    return BeautifulSoup(some_xml, "xml")

module_b.py

import module_a
def main():
    # How does this line know what to do with .find()? or .string?
    print(module_a.function().find("name").string) 

这就是像 python 这样的动态语言的美妙之处。 module_a.function() 告诉 python 到:

  • 转到模块 a
  • 查找名为 "function" 的函数并调用它
  • 获取返回的对象,查找"find"并调用它
  • 获取返回的对象,查找"string"并调用它

由于所有这些查找都是在调用函数或方法时动态发生的,因此 module_b 不必为 bs4string 预定义接口。它只是在寻找一种可能来自任何地方的名为 "find" 的方法。事实上,module_a 可以交换一些其他实现,只要被调用的方法仍然存在,它仍然有效。

from bs4 import BeautifulSoupbs4 模块(以及 导入的任何子模块)导入 python。完成后,您可以在 sys.modules 中看到该模块。然后它进入 bs4,查找 BeautifulSoup 并将 class 添加到 module_a 的命名空间。该模块现在可用于所有其他导入的模块......只是他们不知道它,因为他们没有导入它。仅使用 bs4 生成的对象的模块永远不需要直接查看它。