我试图找到一个全面的指南,是否最好使用导入模块或从模块导入。我刚刚开始学习Python,我正试图从最佳实践开始。

基本上,我希望任何人都能分享他们的经验,其他开发者有什么偏好,以及避免任何陷阱的最佳方法是什么?


当前回答

import module和from module import foo之间的区别主要是主观的。选择一个你最喜欢的,并始终如一地使用它。这里有几点可以帮助你做决定。

导入模块

优点: 更少地维护您的导入语句。不需要添加任何额外的导入就可以开始使用模块中的另一个项 缺点: 输入模块。Foo在你的代码中可能是乏味和冗余的(单调可以通过使用import module作为mo然后输入mo. Foo来最小化)

从模块导入foo

优点: 使用foo时输入更少 对可以访问模块的哪些项有更多的控制 缺点: 要使用模块中的新项,必须更新import语句 你失去了关于foo的上下文。例如,与math.ceil()相比,ceil()的作用就不太清楚了。

这两种方法都可以,但不要使用from module import *。

对于任何合理的大型代码集,如果您导入*,则可能会将其固化到模块中,无法删除。这是因为很难确定代码中使用的哪些项来自'module',这很容易让你认为你不再使用导入,但很难确定。

其他回答

我刚刚发现这两种方法之间还有一个微妙的区别。

如果模块foo使用以下导入:

from itertools import count

这样,模块bar就会错误地使用count,就好像它是在foo中定义的,而不是在itertools中定义的一样:

import foo
foo.count()

如果foo使用:

import itertools

这种错误仍有可能发生,但不太可能发生。酒吧需要:

import foo
foo.itertools.count()

这给我带来了一些麻烦。我有一个模块错误地从一个没有定义它的模块导入了一个异常,只从其他模块导入了它(使用from module import SomeException)。当不再需要导入并删除时,出现问题的模块就被破坏了。

我个人总是用

from package.subpackage.subsubpackage import module

然后访问所有

module.function
module.modulevar

等。原因是,与此同时,您可以进行简短的调用,并且可以清楚地定义每个例程的模块名称空间,如果您必须在源代码中搜索给定模块的使用情况,这是非常有用的。

不用说,不要使用import *,因为它会污染您的命名空间,并且它不会告诉您给定函数来自何处(来自哪个模块)

当然,如果在两个不同的包中对两个不同的模块使用相同的模块名,您可能会遇到麻烦,例如

from package1.subpackage import module
from package2.subpackage import module

在这种情况下,您当然会遇到麻烦,但是强烈地暗示您的包布局有缺陷,您必须重新考虑它。

我正在回答一个类似的问题,但在我发布之前,发帖者删除了它。这里有一个例子来说明这些区别。

Python库可以有一个或多个文件(模块)。为例子,

package1
  |-- __init__.py

or

package2
  |-- __init__.py
  |-- module1.py
  |-- module2.py

我们可以在任何基于设计需求的文件中定义python函数或类。

让我们来定义

在mylibrary1下的__init__.py中的Func1 () mylibrary2下的module2.py中的Foo()。

我们可以使用这些方法之一访问func1()

import package1

package1.func1()

or

import package1 as my

my.func1()

or

from package1 import func1

func1()

or

from package1 import *

func1()

我们可以使用以下方法之一来访问foo():

import package2.module2

package2.module2.foo()

or

import package2.module2 as mod2

mod2.foo()

or

from package2 import module2

module2.foo()

or

from package2 import module2 as mod2

mod2.foo()

or

from package2.module2 import *

foo()

正如Jan Wrobel提到的,不同导入的一个方面是导入的披露方式。

模块mymath

from math import gcd
...

使用mymath:

import mymath
mymath.gcd(30, 42)  # will work though maybe not expected

如果我导入gcd只是为了内部使用,而不向mymath的用户公开它,这可能会很不方便。我经常遇到这种情况,在大多数情况下,我想“保持我的模块干净”。

除了Jan Wrobel提出的通过使用导入数学来掩盖这一点之外,我已经开始通过使用前导下划线来隐藏导入,以避免公开:

# for instance...
from math import gcd as _gcd
# or...
import math as _math

在较大的项目中,这种“最佳实践”允许我准确地控制向后续导入公开的内容和不公开的内容。这使我的模块保持干净,并在一定规模的项目中回报。

这是我当前目录的目录结构:

. └─a └─b └─c

The import statement remembers all intermediate names. These names have to be qualified: In[1]: import a.b.c In[2]: a Out[2]: <module 'a' (namespace)> In[3]: a.b Out[3]: <module 'a.b' (namespace)> In[4]: a.b.c Out[4]: <module 'a.b.c' (namespace)> The from ... import ... statement remembers only the imported name. This name must not be qualified: In[1]: from a.b import c In[2]: a NameError: name 'a' is not defined In[2]: a.b NameError: name 'a' is not defined In[3]: a.b.c NameError: name 'a' is not defined In[4]: c Out[4]: <module 'a.b.c' (namespace)>


注意:当然,我在第1步和第2步之间重新启动了Python控制台。