只是为了给你一些背景信息:
我必须将一些MATLAB代码翻译成Python 3代码,但在这里我遇到了一个小问题。
Matlab的:
for i in 1:num_nodes
for j in 1:num_nodes
K{i,j} = zeros(3,3);
我将其翻译成:
k_topology = [[]]
for i in range(x):
for i in range(x):
k_topology[[i][j]].extend(np.zeros(3,3))
此外,在Matlab代码中还有第三个循环:
for k in 1:3
K{i,j}(k,k) = -1
哪种......也让我心烦意乱?
事实上,我并没有真正看到如何将这种变量转换为Python。另外,我猜我的Python代码有点“破碎” - 而且我并没有真的要求任何人改进它 - 所以我只是问哪个是最好的将Matlab的单元格转换为Python的方法?
根据kazemakase的回答,我终于找到了一些显然简单来翻译它,使用列表理解 - 。实际的Python代码现在看起来像这样:
k_topology = [[np.zeros((3,3)) for j in range(self.get_nb_nodes_from_network())]\
for i in range(self.get_nb_nodes_from_network())]
在输出中看起来像这样:
[[array([[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]]),
array([[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]]),
array([[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]])], ..., [array(...)]]
(在这里粘贴它真的太多了,但我认为你得到了它。)
答案 0 :(得分:3)
您需要问的第一个问题是“是一个Matlab单元格,什么可能是一个合适的相应Python类型?”
如果我从我糟糕的旧Matlab时代中正确地记得,一个单元格就是一个容纳混合类型内容的容器。它类似于动态类型的数组或矩阵。它是多维索引的。
Python是动态类型的,因此任何Python contianer都可以基本实现此功能。 Python中的列表被编入索引,因此嵌套列表可以工作 - 但是设置和访问它们有点奇怪:
K = [[None] * num_nodes for _ in range(num_nodes)]
K[i][j] # need two indices to access elements of a nested list.
对于特定场景,字典更好地反映了Matlab语法。虽然ditionary只接受一个索引,但我们可以利用这样一个事实,即元组可以不带括号声明,并且字典可以将元组作为索引:
K = {}
for i in range(num_nodes):
for j in range(num_nodes):
K[i, j] = np.zeros((3, 3))
for k in 1:3
K[i, j][k, k] = -1
虽然字典在语法上更简洁,但元素访问的可能性要低于嵌套列表。嵌套看起来与Matlab代码不同。选择取决于性能或与原始代码的相似性。但是,如果性能是一个问题,那么还有很多事情要考虑,无论如何。总结:没有一种最好的方法。
由于OP明确要求不改进代码,我明确要求他/她忽略这部分答案。
构建对角矩阵的更好方法是使用np.ones
而不是在对角线元素上循环。
K = {}
for i in range(num_nodes):
for j in range(num_nodes):
K[i, j] = -np.ones((3, 3))
此外,如果这是首选方法,则可以在没有(很多)事先初始化的情况下构建嵌套列表:
K = []
for i in range(num_nodes):
K.append([])
for j in range(num_nodes):
K[-1].append(-np.ones((3, 3)))
现在,为了我的灵魂的平安,让我分开提供关于OP代码的反馈:
k_topology = [[]] for i in range(x): for i in range(x): k_topology[[i][j]].extend(np.zeros(3,3))
i
。永远不会定义j
。[[i][j]]
使用一个元素i
构建一个列表,并尝试获取第j个元素。如果j
不是0,则会导致错误。list.extend
a将参数的所有元素分别附加到列表中 - 在本例中为单个行。使用list.append
是正确的,因为整个3x3矩阵应作为K中的一个元素附加。np.zeros(3, 3)
应为np.zeros((3, 3))
(假设np
是numpy
的别名),因为该函数的形状是第一个参数,而不是多个参数。答案 1 :(得分:0)
使用我在链接帖子中演示的Octave / scipy save / loadmat:
在Octave会议中
SAPbobsCOM.Company oCompany = new SAPbobsCOM.Company();
访问一个单元格:
>> num_nodes=3
num_nodes = 3
>> num_nodes=3;
>> K=cell(num_nodes, num_nodes);
>> for i = 1:num_nodes
for j = 1:num_nodes
K{i,j} = zeros(2,2);
end
end
>> K
K =
{
[1,1] =
0 0
0 0
[2,1] =
0 0
0 0
etc
访问一个单元格的一个元素:
>> K{1,2}
ans =
0 0
0 0
在Python中
>> K{1,2}(1,1)
ans = 0
>> save -7 kfile.mat K
In [31]: from scipy import io
In [32]: data = io.loadmat('kfile.mat')
In [34]: data
Out[34]:
{'K': array([[array([[ 0., 0.],
[ 0., 0.]]),
array([[ 0., 0.],
[ 0., 0.]]),
array([[ 0., 0.],
[ 0., 0.]])],
[array([[ 0., 0.],
[ 0., 0.]]),
array([[ 0., 0.],
[ 0., 0.]]),
array([[ 0., 0.],
[ 0., 0.]])],
[array([[ 0., 0.],
[ 0., 0.]]),
array([[ 0., 0.],
[ 0., 0.]]),
array([[ 0., 0.],
[ 0., 0.]])]], dtype=object),
'__globals__': [],
'__header__': b'MATLAB 5.0 MAT-file, written by Octave 4.0.0, 2017-02-15 19:05:44 UTC',
'__version__': '1.0'}
In [35]: data['K'].shape
Out[35]: (3, 3)
In [36]: data['K'][0,0].shape
Out[36]: (2, 2)
In [37]: data['K'][0,0][0,0]
Out[37]: 0.0
将loadmat
视为2d对象dtype数组;常规矩阵是2d数字数组。对象数组在很多方面类似于嵌套的Python列表。