有没有办法让我干燥 Python 文件中的常见导入?

Sha*_*ani 7 python python-import

在 C# 中,全局使用的概念可用于 DRY(不要重复)using许多文件中的许多常见语句。

现在,我们在许多 Python 文件中都有许多类似的导入。我们是否可以使用类似的策略来减少样板代码?

Bri*_*ian 13

您可以创建一个“prelude”模块,其唯一目的是由其他模块全局导入。这个想法可以在其他编程语言中找到,例如std::preludeRust 和PreludeHaskell。

例如,创建一个prelude.py包含以下内容的文件

from .sprockets import LeftSprocket, RightSprocket, make_sprocket
from .widgets import FooWidget, BarWidget
from .util import sprocket2widget, widget2sprokect
Run Code Online (Sandbox Code Playgroud)

然后从您想要使用它的任何脚本中将其导入为

from my_package.my_module.prelude import *
Run Code Online (Sandbox Code Playgroud)

前奏中的所有名字 ( LeftSprocket,FooWidget等)将立即可用。

这种方法有一些很好的优点:

  • 对于最终用户来说,它完全是可选的。用户可以自由决定是使用 prelude 还是显式导入他们需要的模块。
  • 它对包裹的其余部分没有影响。提供前奏不需要修改任何其他模块或以其他方式重新组织您的包。

也就是说,我不一定建议为所有项目创建前奏。它有一些明显的缺点:

  • 现在有多个模块导出相同的名称,因此 IDE 可能很难自动完成导入。您最终可能会得到 IDE 的建议,例如my_package.my_module.prelude import FooWidget代替my_package.my_module.widget import FooWidget. 这也可能会让用户感到困惑,如果不调查这两个模块,他们就不会知道FooWidget两个模块中的 s 是相同还是不同。

  • 这使得全球名称的来源变得不那么明显。如果您全局导入前奏,则没有简单的方法可以告诉哪些名称可用以及它们来自哪些模块。这违背了Python的禅宗显式优于隐式。

  • 存在名称冲突的风险。例如考虑这个最近的问题。那里的问题与 OP 有关,包括导入from PIL import Imagefrom tkinter import *,后者默默地重新定义Imagetkinter.Image

另请参阅为什么“import *”不好?