除了一本书,我还提供了一个Python程序,我现在正在深入挖掘。
该程序使用名为globdat
的全局数据结构,在特定例程中,globdat
内的numpy数组被分配给局部变量:
a = globdat.array
然后在下面的while循环中,每次迭代都会根据以下内容更新变量a
:
a[:] += da[:]
此操作的结果是globdat.array
已更新,这将在后续操作中使用。
此处是否需要使用[:]
,还是仅用于表示它还会克隆到globdat.array
?任何人都可以澄清这种编码风格吗?
答案 0 :(得分:4)
这句话很讨厌:
a[:] += da[:]
它转化为:
a.__setitem__(slice(None),
a.__getitem__(slice(None)).__iadd__(da.__getitem__(slice(None))))
这会使两个列表都不必要的副本。
假设a
和da
是列表,您可以更合理地使用extend()
方法:
a.extend(da)
答案 1 :(得分:4)
如果要修改列表,而不是用新列表替换它,则需要使用切片语法。
data <- sub240
while(rsquared.differ > 0.00001 && niter <=30){
# do stuff
}
在这种情况下,a[:] = da[:]
将总是修改列表,因此切片是多余的。
这可能是cargo cult programming的完美示例。
答案 2 :(得分:4)
右边的第二个[:]
是多余的。它只是在连接中使用它之前复制da
,这是毫无意义的。
我们离开了:
a[:] += da
首先,让我们了解a += da
的作用。它映射到:
a = a.__iadd__(da)
对__iadd__
的调用扩展了原始列表a
,并返回self
,即对列表的引用。之后发生的赋值在这种情况下无效(与a=a
相同)。
这实现了最初的目标,即扩展全局数组。
现在,a[:] += da
做了什么?它映射到:
a[:] = a[:].__iadd__(da)
或者更乏味地说:
a.__setitem__(slice(None), a.__getitem__(slice(None)).__iadd__(da))
为了便于阅读,请将其写为(不是有效的python语法):
a.__setitem__(:, a.__getitem__(:).__iadd__(da))
所以a[:].__iadd__(da)
:
a
(来电是a2
)da
连接到a2
到位a2
然后是作业a[:] = ...
:
a
中的所有值替换为a2
中的所有值。这样也达到了原来的目标,但效率却低得多。
this question的答案中有关于这些内容的一些有趣的细节。