关于python:“import *”究竟是什么导入的?

What exactly does “import *” import?

在python中,import *究竟导入了什么?是否导入包含文件夹中的__init__.py

例如,是否需要申报from project.model import __init__from project.model import *是否足够?


与其他形式的进口相比,from xyz import *的"优势"在于它进口一切(好吧,几乎是……[见下文(a)项]当前模块下指定模块的所有内容。这允许使用导入模块中的各种对象(变量、类、方法等),而不必在它们前面加上模块名称。例如

1
2
3
4
5
>>> from math import *
>>>pi
3.141592653589793
>>>sin(pi/2)
>>>1.0

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

  • 提供命名空间冲突的机会(例如,如果在导入之前有一个变量名pi)
  • 如果导入的对象数量很大,则可能效率低下
  • 没有显式地记录变量/方法/类的来源(最好有这个程序的"自我文档"以便将来访问代码)

因此,我们通常将此导入*实践限制为特殊测试等。正如@denilson-s_-maia指出的那样,一些库(例如pygame)有一个子模块,其中定义了所有最常用的常量和函数,并且这些子模块有效地设计为与import *一起导入。除这些特殊子模块外,最好是……

只显式导入一些对象

1
2
3
4
5
6
7
>>>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

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

1
2
3
4
5
6
7
8
9
10
  >>>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.requesturllib.errorsurllib.response等子模块,一个常见的混淆点是

from urllib import *

将导入所有这些子模块。事实并非如此:我们需要用from urllib.request import *等单独明确地导入这些模块。顺便说一句,这并不特定于import *,plain import也不会导入子模块(当然,*通常是"一切"的简写,它可能误导人们认为所有子模块和eve其他的东西会被进口)。


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

它主要是一个方便的快捷方式,仅用于交互式口译员会话:正如其他答案所建议的,不要在程序中使用它。

根据谷歌的python风格指南,我的建议是只导入模块,而不从模块中导入类或函数(或其他名称)。严格遵循这一点有助于提高清晰度和准确性,并避免在导入"模块内的内容"时可能出现的微妙陷阱。

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


是的,是的。它导入所有内容(不是私有变量,即名称以___开头的变量),您应该尽量不要根据"在python中正确导入模块"来使用它,以避免污染本地名称空间。

这是足够的,但一般来说,您应该按照"了解python导入"来执行import project.model,它已经导入了__init__.py,但如果使用太多,可能会变得过于冗长,或者使用import project.model as pmimport project.model as model,以便在以后使用时节省一些按键。

按照亚历克斯的建议"import*"import"到底是什么?


如果project.model是一个包,那么import project.model所指的模块来自.../project/model/__init__.pyfrom project.model import *__init__.py的名称空间中的所有内容转储到您的名称空间中。它不会自动对模型中的其他模块执行任何操作。首选的样式是__init__.py不包含任何内容。

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


如果有问题的模块(在您的例子中是project.model)定义了一个名为__all__的托管列表,那么该列表中的每个命名变量都将被导入。如果没有这样的变量,它将导入所有内容。


下面是一个很好的方法,可以查看从模块导入了哪些星形/星号(*)。

1
2
3
4
before = dir()
from math import *
after = dir()
print(set(after) - set(before))

返回:

1
{'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'}

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