59

import *在 Python 中, import到底是什么?它是否在包含文件夹中找到导入__init__.py

例如,是否需要声明from project.model import __init__,或者是否from project.model import *足够?

4

6 回答 6

68

from xyz import *与其他形式的导入相比,它的“优点”是它从当前模块下的指定模块导入所有内容(嗯,几乎...... [参见下面的(a)] 所有内容)。这允许使用导入模块中的各种对象(变量、类、方法...),而无需在它们前面加上模块的名称。例如

>>> from math import *
>>>pi
3.141592653589793
>>>sin(pi/2)
>>>1.0

然而,这种做法(将 * 导入当前命名空间)是不鼓励的,因为它

  • 提供命名空间冲突的机会(例如,如果您在导入之前有一个变量名 pi)
  • 如果导入的对象数量很大,可能效率低下
  • 没有明确记录变量/方法/类的起源(很高兴有这个程序的“自我文档”以供将来访问代码)

因此,通常我们将这种 import * 实践限制为临时测试等。正如@Denilson-Sá-Maia 所指出的,一些库(例如 pygame)有一个子模块,其中定义了所有最常用的常量和函数,并且这些子模块被有效地设计为使用import *. 除了这些特殊的子模块之外,最好...:

仅显式导入一些对象

>>>from math import pi
>>>pi
>>>3.141592653589793
>>> sin(pi/2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'sin' is not defined

在其自己的命名空间下导入模块(或其别名,特别是如果这是一个长名称,并且程序多次引用其对象)

  >>>import math
  >>>math.pi
  >>>3.141592653589793
  etc..


  >>>import math as m  #bad example math being so short and standard...
  >>>m.pi
  >>>3.141592653589793
  etc..

请参阅有关此主题的 Python 文档

(a) 具体来说,什么是进口的from xyz import *
如果 xyz 模块定义了一个__all__变量,它将导入此序列中定义的所有名称,否则它将导入所有名称,但以下划线开头的名称除外。

注意许多库都有子模块。例如,标准库urllib包括子模块,如,urllib.request等。一个常见的混淆点是urllib.errorsurllib.response

from urllib import *

将导入所有这些子模块。情况并非如此:需要单独显式导入这些,比如说,from urllib.request import *等等。顺便说一下,这不是特定于import *,plainimport也不会导入子模块(但当然,*这通常是“一切”的简写可能误导人们认为所有子模块和其他所有内容都将被导入)。

于 2010-03-02T03:56:25.443 回答
15

它导入(到当前命名空间)模块(或包)在其__all__属性中列出的任何名称——缺少这样的属性,所有名称不以_.

它主要用作仅在交互式解释器会话中使用的便捷快捷方式:正如其他答案所建议的那样,不要在程序中使用它。

根据Google 的 Python 风格指南,我的建议是只导入模块而不是模块中的类或函数(或其他名称)。严格遵循这一点可以提高清晰度和准确性,并避免在导入“模块内的东西”时可能出现的微妙陷阱。

导入一个包(或其中的任何东西)本质上加载并执行包的__init__.py——该文件定义了包的主体。但是,它不会__init__在您当前的命名空间中绑定名称(因此从这个意义上说,它不会导入该名称)。

于 2010-03-02T03:47:36.560 回答
4

是的,它确实。它导入所有内容(不是私有变量,即:名称以_or开头的变量__),您应该尽量不要根据“在 Python 中正确导入模块”使用它,以免污染本地命名空间。

这已经足够了,但通常你应该按照“理解 python 导入import project.model”做已经导入的,但是如果你使用它太多会变得太罗嗦,或者在你以后使用它时节省一些击键。__init__.pyimport project.model as pmimport project.model as model

遵循 Alex 在“ “import *”究竟是什么导入? ”中的建议。

于 2010-03-02T03:35:32.760 回答
4

如果project.model是包,则引用的模块import project.model来自.../project/model/__init__.py. 将' 的命名空间中的from project.model import *所有内容转储到您的命名空间中。__init__.py它不会自动对模型中的其他模块执行任何操作。首选样式是__init__.py不包含任何内容。

从来没有使用过import *。它使您的代码不可读和不可维护。

于 2010-03-02T03:39:43.667 回答
4

这是查看从模块导入的星号/星号 ( * ) 的好方法:

before = dir()
from math import *
after = dir()
print(set(after) - set(before))

返回:

{'modf', 'pow', 'erfc', 'copysign', 'sqrt', 'atan2', 'e', 'tanh', 'pi', 'factorial', 'cosh', 'expm1', 'cos', 'fmod', 'frexp', 'log', 'acosh', 'sinh', 'floor', 'isclose', 'lgamma', 'ceil', 'gcd', 'ldexp', 'hypot', 'radians', 'atan', 'isnan', 'atanh', 'before', 'isinf', 'fabs', 'isfinite', 'log10', 'nan', 'tau', 'acos', 'gamma', 'asin', 'log2', 'tan', 'degrees', 'asinh', 'erf', 'fsum', 'inf', 'exp', 'sin', 'trunc', 'log1p'}

我正在使用自己的模块,明确导入所有内容,但要导入的内容列表太长了。因此,必须使用此方法来获取 * 已导入内容的列表。

于 2019-03-01T10:32:30.497 回答
2

如果有问题的模块(project.model在您的情况下)定义了一个名为的字符串__all__列表,则导入该列表中的每个命名变量。如果没有这样的变量,它将导入所有内容。

于 2010-03-02T03:43:20.243 回答