知道Numpy和普通python有什么不同吗?

2024-04-29 15:06:52 发布

您现在位置:Python中文网/ 问答频道 /正文

各位

有没有一个gotchas的集合,其中Numpy与python不同, 那些让人困惑又耗费时间的观点?

"The horror of that moment I shall never never forget !"
"You will, though," the Queen said, "if you don't make a memorandum of it."

例如,无论在哪里,南斯都是麻烦。 如果你能解释而不运行它,给自己一个点--

from numpy import array, NaN, isnan

pynan = float("nan")
print pynan is pynan, pynan is NaN, NaN is NaN
a = (0, pynan)
print a, a[1] is pynan, any([aa is pynan for aa in a])

a = array(( 0, NaN ))
print a, a[1] is NaN, isnan( a[1] )

(我不是在敲纽比,那里有很多好的工作,只是觉得一个常见问题或gotchas的Wiki会有用。)

编辑:我希望收集六个gotchas(对学习Numpy的人来说是个惊喜)。
如果有共同的问题或者更好的解释, 我们可以讨论将它们添加到社区Wiki(在哪里?) 看来我们到目前为止还不够。


Tags: ofthenumpyiswiki时间nanarray
3条回答

因为__eq__不返回bool,所以在任何类型的容器中使用numpy数组都会防止在没有特定于容器的工作的情况下进行相等性测试。

示例:

>>> import numpy
>>> a = numpy.array(range(3))
>>> b = numpy.array(range(3))
>>> a == b
array([ True,  True,  True], dtype=bool)
>>> x = (a, 'banana')
>>> y = (b, 'banana')
>>> x == y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

这是一个可怕的问题。例如,不能为使用TestCase.assertEqual()的容器编写unittests,而必须编写自定义比较函数。假设我们编写了一个变通函数special_eq_for_numpy_and_tuples。现在我们可以在unittest中执行此操作:

x = (array1, 'deserialized')
y = (array2, 'deserialized')
self.failUnless( special_eq_for_numpy_and_tuples(x, y) )

现在我们必须对可能用于存储numpy数组的每个容器类型执行此操作。此外,__eq__可能返回bool而不是bools数组:

>>> a = numpy.array(range(3))
>>> b = numpy.array(range(5))
>>> a == b
False

现在,我们每个特定于容器的等式比较函数也必须处理这种特殊情况。

也许我们可以用一个亚类来修补这个疣?

>>> class SaneEqualityArray (numpy.ndarray):
...   def __eq__(self, other):
...     return isinstance(other, SaneEqualityArray) and self.shape == other.shape and (numpy.ndarray.__eq__(self, other)).all()
... 
>>> a = SaneEqualityArray( (2, 3) )
>>> a.fill(7)
>>> b = SaneEqualityArray( (2, 3) )
>>> b.fill(7)
>>> a == b
True
>>> x = (a, 'banana')
>>> y = (b, 'banana')
>>> x == y
True
>>> c = SaneEqualityArray( (7, 7) )
>>> c.fill(7)
>>> a == c
False

这样做似乎是对的。类还应该显式导出元素级比较,因为这通常很有用。

我觉得这个很有趣:

>>> import numpy as n
>>> a = n.array([[1,2],[3,4]])
>>> a[1], a[0] = a[0], a[1]
>>> a
array([[1, 2],
       [1, 2]])

另一方面,对于Python列表,它按预期工作:

>>> b = [[1,2],[3,4]]
>>> b[1], b[0] = b[0], b[1]
>>> b
[[3, 4], [1, 2]]

有趣的是:numpy本身在shuffle函数中有一个bug,因为它使用了那个符号:-)(请参见here)。

原因是,在第一种情况下,我们处理的是数组的视图,因此值会被就地覆盖。

对我来说,最大的问题是几乎所有的标准运算符都被重载以分布在数组中。

定义列表和数组

>>> l = range(10)
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> import numpy
>>> a = numpy.array(l)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

乘法复制python列表,但分布在numpy数组上

>>> l * 2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a * 2
array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])

python列表中没有定义Addition和division

>>> l + 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "int") to list
>>> a + 2
array([ 2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
>>> l / 2.0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for /: 'list' and 'float'
>>> a / 2.0
array([ 0. ,  0.5,  1. ,  1.5,  2. ,  2.5,  3. ,  3.5,  4. ,  4.5])

Numpy重载有时将列表视为数组

>>> a + a
array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])
>>> a + l
array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])

相关问题 更多 >