从X导入a'与'import X; X.a

10 投票
9 回答
3237 浏览
提问于 2025-04-11 09:28

我看到一些Python程序员经常使用一种风格(我们称之为风格1):

import some_module
# Use some_module.some_identifier in various places.

支持这种风格的一个理由是,大家都知道“明确比隐含好”这句话。我也见过其他程序员使用另一种风格(风格2):

from some_module import some_identifier
# Use some_identifier in various places.

我觉得风格2的主要好处在于可维护性——特别是当我想用一个模块替换另一个模块时,比如用某个模块替换成另一个模块,这种情况在“鸭子类型”的理念下很常见。我还觉得风格2在“可读性很重要”这句话上更有优势。虽然我个人不太同意,但有人可能会说,使用风格1时,搜索和替换也是一个不错的选择。

补充:有人提到可以用as来解决风格1中从some_module切换到some_other_module的问题。我忘了提的是,通常我们会决定在当前模块中实现some_identifier,这会让创建一个等效的some_module容器变得有点尴尬。

9 个回答

2

我更喜欢先使用 import X,然后尽量用 X.a

不过在一些像Django这样的大框架中,情况就不一样了。这些框架里的模块名字通常很长,而且它们的例子里都说要用 from django.conf import settings,这样可以省去到处写 django.conf.settings.DEBUG 的麻烦。

如果模块名字很复杂,那我就会例外,直接用 from X.Y.Z import a

5

有了下面这种写法:

import some_other_module as some_module

所以关于第二种风格的可维护性这个说法就不太适用了。

我个人比较喜欢用第一种风格。通常在一个普通的Python程序中,我发现我只会明确提到导入的包名几次。其他时候都是在用对象的方法,而这些方法当然不需要提到导入的包。

6

这两种情况都有用,所以我觉得这不是一个非此即彼的问题。

我会考虑在以下情况下使用 import x,y,z 来导入模块:

  • 要导入的东西数量比较少。

  • 导入的函数的用途很明显,即使不提模块名。如果这些名字比较普通,可能会和其他的名字冲突,而且信息量不大。比如,看到 remove 这个名字并不能告诉你太多,但 os.remove 可能会让你知道你在处理文件。

  • 名字之间没有冲突。这个点比上面更重要。绝对不要做这样的事情:

     from os import open
    

import module [as renamed_module] 的好处是,它能给你更多关于你在调用什么的上下文信息。不过,它的缺点是,如果模块本身没有提供更多信息,这样会显得有点杂乱,而且性能稍微差一点(需要查找两次,而不是一次)。

不过在测试的时候,这种方式也有优势(比如,可以用一个模拟对象替代 os.open,而不需要更改每个模块),在使用可变模块时应该使用这种方式,例如:

import config
config.dburl = 'sqlite:///test.db'

如果不确定的话,我总是会选择 import module 这种风格。

撰写回答