import *" 究竟导入了什么?
在Python中,import *
到底导入了什么呢?它会导入包含文件夹里的__init__.py
吗?
举个例子,是否需要写from project.model import __init__
,还是说from project.model import *
就够了?
6 个回答
这里有一个很好的方法,可以查看星号(*)从一个模块中导入了哪些内容:
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'}
我在使用自己的模块时,都是明确地导入每一个内容,但要导入的东西列表变得太长了。所以,我不得不使用这个方法来获取星号导入的内容列表。
当你导入一个模块(或包)时,它会把模块里在__all__
属性中列出的名字导入到当前的命名空间。如果没有这个属性,它会导入所有不以_
开头的名字。
这个功能主要是为了在交互式解释器中方便使用:正如其他回答所提到的,不要在程序中使用它。
根据谷歌的Python风格指南,我建议只导入模块,而不是从模块中导入类或函数(或其他名字)。这样做可以让代码更清晰、更准确,避免在导入“模块内部的东西”时可能遇到的微妙问题。
导入一个包(或包中的任何东西)时,会自动加载并执行包里的__init__.py
文件——这个文件定义了包的内容。不过,它不会在你的当前命名空间中绑定__init__
这个名字(所以从这个意义上说,它并没有导入这个名字)。
使用 from xyz import *
这种方式导入的“好处”是,它可以从指定的模块中导入几乎所有的东西(当然,几乎是指几乎所有... [见下面(a)的说明])。这样一来,你就可以直接使用导入模块里的各种对象(比如变量、类、方法等),而不需要在前面加上模块的名字。举个例子:
>>> from math import *
>>>pi
3.141592653589793
>>>sin(pi/2)
>>>1.0
不过,这种把所有东西都导入当前命名空间的做法是被不推荐的,原因有:
- 可能会导致命名冲突(比如你在导入之前就有一个叫 pi 的变量)
- 如果导入的对象数量很大,可能会效率低下
- 没有明确记录变量、方法或类的来源(这样在以后查看代码时就不太方便了)
所以通常我们会把这种导入 * 的做法限制在临时测试等场合。正如 @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.errors
、urllib.response
等子模块。一个常见的误解是:
from urllib import *
会导入所有这些子模块。其实并不是这样:你需要单独明确导入这些子模块,比如用 from urllib.request import *
等等。顺便说一下,这并不是 import *
特有的,普通的 import
也不会导入子模块(当然,*
通常是“所有”的简写,可能会误导人们以为所有子模块和其他所有东西都会被导入)。