哈哈!
我有两块代码,一块有效,另一块无效。唯一的区别是我不使用的numpy模块的注释行代码。当我从未引用"npm"时,为什么需要导入该模型?
此命令有效:
import numpy as np
import numpy.matlib as npm
V = np.array([[1,2,3],[4,5,6],[7,8,9]])
P1 = np.matlib.identity(V.shape[1], dtype=int)
P1
此命令无效:
import numpy as np
#import numpy.matlib as npm
V = np.array([[1,2,3],[4,5,6],[7,8,9]])
P1 = np.matlib.identity(V.shape[1], dtype=int)
P1
上面得到这个错误:
AttributeError: 'module' object has no attribute 'matlib'
提前感谢!
简短回答
这是因为numpy.matlib
是numpy
的可选子包,必须单独导入。
此功能的原因可能是:
- 特别是对于
numpy
,numpy.matlib
子模块重新定义了numpy
的函数,以返回矩阵而不是ndarrays,这是许多人可能不想要的可选功能 - 更一般地说,在不加载可能缓慢加载的模块的情况下加载父模块,而许多用户可能并不经常需要该模块
- 可能是命名空间分离
当只导入numpy
而不导入子包matlib
时,Python将查找.matlib
作为numpy
包的属性。在未导入numpy.matlib
的情况下,尚未将此属性分配给numpy
(请参阅下面的讨论)
子模块和绑定
如果您想知道为什么np.matlib.identity
在不使用关键字npm
的情况下工作,那是因为当您导入子模块matlib
时,父模块numpy
(在您的情况下命名为np
)将被赋予绑定到子模块的属性matlib
。只有当您首先定义numpy
时,这才有效。
参考:
当使用任何机制加载子模块时(例如importlib API、import或import-from语句,或内置的import()),会在父模块的命名空间中放置到子模块对象的绑定。
导入和__init__.py
导入内容的选择在模块目录中的模块各自的__init__.py
文件中确定。您可以使用dir()
函数来查看各个模块定义的名称。
>> import numpy
>> 'matlib' in dir(numpy)
# False
>> import numpy.matlib
>> 'matlib' in dir(numpy)
# True
或者,如果直接查看numpy
的__init__.py
文件,则会发现matlib
没有导入。
跨子模块的命名空间
如果您想知道命名空间是如何在上顺利复制的;
matlib
源代码运行此命令以在numpy
命名空间上复制:
import numpy as np # (1)
...
# need * as we're copying the numpy namespace
from numpy import * # (2)
...
__all__ = np.__all__[:] # copy numpy namespace # (3)
第(2)行,from numpy import *
尤为重要。因此,您会注意到,如果只导入numpy.matlib
,您仍然可以使用所有numpy
模块,而无需导入numpy
!
如果没有第(2)行,第(3)行中的名称空间副本将仅附加到子模块。有趣的是,由于第(3)行,您仍然可以执行这样一个有趣的命令。
import numpy.matlib
numpy.matlib.np.matlib.np.array([1,1])
这是因为np.__all__
连接到numpy.matlib
的np
(通过线路(1)导入)。
您从未使用npm
,但您确实使用了np.matlib
,因此您可以将第二条导入行更改为:
import numpy.matlib
或者你可以保留你的第二条进口线,但使用:
P1 = npm.identity(V.shape[1], dtype=int)
不使用np.identity
有什么原因吗?
P1 = np.identity(V.shape[1], dtype=int)
此模块包含numpy命名空间中的所有函数,以及以下返回矩阵而不是ndarrays的替换函数。
除非您与2dnp.matrix
子类绑定,否则最好坚持使用常规的ndarray
版本。
(其他人指出,导入原因是基于numpy
的__init__
规范。numpy
导入了大部分,但不是所有的子模块。它没有自动导入的子模块使用频率较低。这是一种礼貌的说法,You don't really need this module
)