python3 / numpy:添加复数时添加不一致

时间:2015-12-16 19:02:50

标签: python numpy complex-numbers in-place

我正在测试一段代码并遇到以下行为。虽然我自己找到了一个解释和解决方案(this看起来虽然不相同),但我想问一下,如果你们中有人有更多要补充的话。

a)我无法在一个numpy数组中添加一个复数     创建为真实,但我可以使用标量变量

b)警告信息仅在有限数量的情况下发出,     而且不是很一致

看看这些命令:

>>> from numpy import *
>>> a5=arange(5)
>>> a5[1:5]+=1j
>>> a5
array([0, 1, 2, 3, 4])
>>> a=8
>>> a+=1j
>>> a
(8+1j)
>>> a5+=1j
__main__:1: ComplexWarning: Casting complex values to real discards the imaginary part
>>> a5[3]+=1j
>>> a5[3]
3
>>> 
你知道吗?只有在尝试向整个向量添加复合体时才会发出ComplexWarning,但在尝试向单个元素或切片添加相同内容时则不会发出z5=arange(5)+0j

这有什么理由吗? (我几乎无法忍受这样的事实,即它不会增加,但肯定不是警告只在一个案例中发出的事实)。 这是一个错误还是一个功能? 怎样才能最好地克服? 至少,当虚构部分因不兼容而被丢弃时,ComplexWarning会出现在所有情况下都不是更好吗?

PS。同时我提供了解决方案: c5=arange(5,dtype="complex")Object.getOwnPropertyDescriptor(myObject, "a")都会按预期行事。但第一个只是部分缓解,因为它表明可以添加一个numpy范围的整数并将其赋值给变量,前提是它是一个复杂的整数,或者是一个新的整数。

2 个答案:

答案 0 :(得分:1)

这被认为是一个问题,但它需要时间来修改,因为修复它会破坏兼容性。

自numpy 1.10起,就地操作和ufunc的默认强制转换规则已更改为“same_kind”,因此您的代码将发出TypeError

TypeError: Cannot cast ufunc add output from dtype('complex128') to dtype('int64') with casting rule 'same_kind'

来自release notes

  

在Numpy 1.10.0中,inplace操作的默认转换将更改为“same_kind”。这肯定会破坏当前忽略警告的一些代码。

答案 1 :(得分:1)

警告是由NumPy每隔时间发出的,但Python的一般警告机制默认情况下仅在第一次发出警告时打印警告。您可以使用warnings.filterwarningswarnings.simplefilter更改此行为。有关详细信息,请参阅warnings module documentation

这是一个示例(使用Python 2.7和NumPy 1.9),显示正在为每个就地操作发出警告。

Python 2.7.10 |Master 2.1.0.dev1829 (64-bit)| (default, Oct 21 2015, 09:09:19) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.6)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from numpy import *
>>> import warnings
>>> warnings.simplefilter('always', ComplexWarning)
>>> a5 = arange(5)
>>> a5[1:5] += 1j
__main__:1: ComplexWarning: Casting complex values to real discards the imaginary part
>>> a5
array([0, 1, 2, 3, 4])
>>> a5 += 1j
__main__:1: ComplexWarning: Casting complex values to real discards the imaginary part
>>> a5[3] += 1j
__main__:1: ComplexWarning: Casting complex values to real discards the imaginary part

你展示的标量添加完全是一个不同的野兽。

>>> a = 8
>>> a += 1j

在这种情况下,+=操作没有进行就地操作(它不能,因为在第一行之后,a是Python int,并且不同NumPy数组,int对象是不可变的。相反,它相当于做a = a + 1j。那是构建一个 new Python complex对象,并重新绑定a来引用该新对象。

你说你“几乎无法忍受它不会增加的事实”。但请注意,没有办法有效地执行此操作:原始数组的内容使用每个项目8个字节进行存储。和的内容是(双精度)复数,因此必须使用每个项目16个字节进行存储。这使得真正的就地操作无法实现。

请注意,在NumPy 1.10中,这些操作将产生TypeError而不是警告。