我应该通过`from numpy import *`使用numpy(或pylab)作为Python环境吗?
我在所有的Python程序中都使用pylab(更具体地说是numpy)。除了极少数例外,我几乎每次都这样做。目前,我已经养成了以以下方式导入numpy的习惯:
from numpy import *
这样做的好处是让numpy看起来就像是Python一开始就有的功能。每个脚本都这样导入numpy,有什么坏处吗?我指的是除了每个脚本/程序会多占一点内存,加载时间会稍长之外。
我觉得每次调用numpy的函数时都要写numpy或者np(比如,np.zeros(3)
)有点麻烦,因为这需要我知道哪些函数是来自numpy的,哪些不是。我其实并不在乎zeros函数是来自numpy还是Python,我只想用它。
你觉得哪种写法更好呢?
5 个回答
我们换个角度来看这个问题。我拿到了你的代码来调试,发现你调用了:
zeros(5)
要检查你的代码里这个是 np.zeros 还是你在别的地方重新定义过,确实挺麻烦的。而且因为 pylab 有930个名字,这种情况很容易发生。
为了更详细地说明其他人说的内容,使用 import *
来引入 numpy 模块是个特别糟糕的选择。
pylab
是为了交互式使用而设计的,在这种情况下使用是没问题的。没有人想在命令行里反复输入 pylab.zeros
,因为可以直接输入 zeros
。但是,一旦你开始写代码,情况就完全不同了。你只需要输入一次,但这段代码可能会一直存在,其他人(比如一年后的你自己)可能会想搞清楚你当时到底在做什么。
除了 @unutbu 提到的关于覆盖 Python 内置的 sum
、float
、int
等的内容,以及大家提到的关于不知道函数来源的问题,numpy
和 pylab
的命名空间都非常大。
numpy
的命名空间里有 566 个函数、变量、类等等。这可真不少!而 pylab
甚至有 930!(而且这些来自很多不同的模块。)
当然,像 zeros
、ones
或 array
这样的函数你大概能猜到它们来自哪里,但 source
、DataSource
或 lib.utils
呢?(如果你使用 from numpy import *
,这些都会出现在你的本地命名空间里。)
如果你的项目稍微大一点,很有可能你会有一个本地变量或者其他文件里的变量,名字和 numpy
里的某个东西很相似。突然间,你会更加在意你到底在调用什么!
再举个例子,你怎么区分 pylab
的 fft
函数和 numpy
的 fft
模块 呢?
这取决于你是这样做:
from numpy import *
from pylab import *
还是这样:
from pylab import *
from numpy import *
fft
在这两种情况下是完全不同的东西,行为也完全不同!(也就是说,在第二种情况下调用 fft
会报错。)
总的来说,你应该始终避免使用 from module import *
,但在 numpy
、scipy
等大型模块的情况下,这尤其是个坏主意,因为它们的命名空间太大了。
当然,以上说的都是在前提下,如果你只是想在命令行里快速绘制一些数据的图表,然后再继续做其他事情,那当然可以使用 pylab
。这就是它的用途。只要不要用这种方式写出后面的人可能会想看懂的代码就行!
</rant>
使用
from numpy import *
会改变any
、all
和sum
的行为。举个例子,any([[False]]) # True all([[True, False], [False, False]]) # True sum([[1,2],[3,4]], 1) # TypeError: unsupported operand type(s) for +: 'int' and 'list'
而如果你使用
from numpy import *
,那么这些值就会完全不同:from numpy import * any([[False]]) # False all([[True, False], [False, False]]) # False sum([[1,2],[3,4]], 1) array([3, 7])
关于名称冲突的完整列表可以通过这种方式找到(感谢 @Joe Kington 和 @jolvi 提醒这一点):
import numpy as np np_locals = set(np.__all__) builtins = set(dir(__builtins__)) print([name for name in np_locals.intersection(builtins) if not name.startswith('__')]) # ['any', 'all', 'sum']
这可能会导致非常混乱的错误,因为在没有使用
from numpy import *
的情况下测试或使用你代码的人,可能会看到和你完全不同的行为。使用多次
from module import *
的方式会让问题更严重,因为会出现更多这种名称冲突。如果你能及时改掉这个坏习惯,就不必担心这种(可能让人困惑的)错误了。如果两个模块都重新定义了同一个名称,导入的顺序也可能会影响结果。
而且这会让你更难搞清楚函数和变量的来源。
虽然可以使用
from numpy import *
仍然访问 Python 的内置函数,但这样做会显得很别扭:from numpy import * any([[False]]) __builtins__.any([[False]])
而且可读性比下面的方式差:
import numpy as np np.any([[False]]) any([[False]])
正如 Python 的哲学所说,
命名空间是个非常好的主意——让我们多用一些吧!
我的建议是,任何脚本中都不要使用 from module import *
。