2

如果我做

a = [1, 2, 7]
a - a[-1]

我明白了TypeError: unsupported operand type(s) for -: 'list' and 'int'

但是,我有一个由 组成的列表bnp.float64并且以下代码有效:

type(b)
# list
b - b[-1]
# array([ 281.04209146,    6.57013103,    0.        ])

我认为这是因为中的数字bnp.float64,并且b在某种程度上被转换为np.array,然后广播发生了。但我仍然发现这种行为令人惊讶:由于列表中的所有元素不需要具有相同的类型,如果b[0]是字符串怎么办?中的操作数 b - b[-1]仍然是listand np.float64,那么为什么b - b[-1]不提高 aTypeError呢?

编辑:有人回答说是不同的listnp.array嗯,我知道。但是b没有np.array. 它的行为就像一个,但它的类型是list,就像我在代码片段中所说的那样。

这是一个最小的工作示例b

b
# [1598.717274996219, 1324.245314569733, 1317.6751835362861]
type(b[0])
# numpy.float64
4

2 回答 2

2

在类似 的表达式A-B中,解释器可以将其实现为A.__sub__(B)B.__rsub__(A)

列表实现muladd不实现sub

In [29]: [1,2,3]*3
Out[29]: [1, 2, 3, 1, 2, 3, 1, 2, 3]
In [30]: [1,2,3]+[1]
Out[30]: [1, 2, 3, 1]
In [31]: [1,2,3]-3
TypeError: unsupported operand type(s) for -: 'list' and 'int'

np.ndarray实现一个__rsub__

In [32]: [1,2,3]-np.array([1,2,3])
Out[32]: array([0, 0, 0])
# np.array([1,2,3]).__rsub__([1,2,3])

而那个方法试图把 LHS 变成一个数组,所以这个表达式是一样的:

In [33]: np.asarray([1,2,3]) - np.array([1,2,3])
Out[33]: array([0, 0, 0])

如果列表包含字符串,则会失败:

In [35]: ['a',2,3]-np.array([1,2,3])
TypeError: ufunc 'subtract' did not contain a loop with signature matching types dtype('<U11') dtype('<U11') dtype('<U11')

因为该列表变成了一个字符串数组:

In [36]: np.asarray(['a',2,3])
Out[36]: 
array(['a', '2', '3'], 
      dtype='<U1')

并且没有实现与字符串 dtype 的数组减法。

我用数组 RHS 写的所有内容都适用,如果它是np.float64. np.float64(10)行为(在大多数情况下)与np.array(10.0).

所以所有这些减法b都是一样的:

 b = [np.float64(10), np.float64(1)]
 b - b[-1]
 b - np.float64(1)
 b - np.array(1.0)
 np.array(b) - np.array(1.0)

总之,如果 RHS 是某种数组,它也会将 LHS 列表转换为数组。从那里开始,问题是 2 个数组是否兼容(在形状和 dtype 方面)。

于 2016-11-28T17:33:58.147 回答
1

TypeError但是,当您制作b[0]字符串时,您不会得到相同的结果。

b=[np.float_(a_) for a_ in a]

b
Out[4]: [1.0, 2.0, 7.0]

b-b[-1]
Out[5]: array([-6., -5.,  0.])

b[0]='a'

b
Out[7]: ['a', 2.0, 7.0]

b-b[-1]
Traceback (most recent call last):

  File "<#>", line 1, in <module>
    b-b[-1]

TypeError: ufunc 'subtract' did not contain a loop with signature matching types dtype('<U32') dtype('<U32') dtype('<U32')

您会TypeErrorsubtract. 在原始版本中,当您获得np.float64for时b[-1],它将整个表达式转换为 numpy 数组。所以如果b[-1]是一个字符串:

b[2]='a'

b-b[-1]
Traceback (most recent call last):

  File "<#>", line 1, in <module>
    b-b[-1]

TypeError: unsupported operand type(s) for -: 'list' and 'str'

你又回到了原来的样子TypeError

于 2016-11-28T13:00:56.333 回答