我对python(2.7(list.remove
函数有点困惑。在删除的文档中,它说:"从列表中删除值为 x 的第一项。如果没有这样的项目,那就是一个错误。
所以,我想这里的值意味着比较是基于平等的(即 ==
(而不是身份(即 is
(。但是,有人可以向我解释以下行为吗?显然,这两种比较都被使用了,但以一种相当奇怪的方式:
import numpy as np
x = np.array([1,2,3])
mylist = [x, 42, 'test', x] # list containing the numpy array twice
print mylist
当然,这将打印:
[array([1, 2, 3]), 42, 'test', array([1, 2, 3])]
目前为止,一切都好。但奇怪的是,以下代码确实执行:
mylist.remove(x)
print mylist
给
[42, 'test', array([1, 2, 3])]
我希望它会抛出错误,因为 numpy 数组不返回布尔语句,而是返回布尔数组。例如,x == x
返回array([ True, True, True], dtype=bool)
.然而,我们的移除愉快地执行。但是,再次调用相同的语句会产生预测的行为:
mylist.remove(x)
抛出一个
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-3-835a19b5f6a9> in <module>()
----> 1 mylist.remove(x)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
这是怎么回事?
> 查看源代码,list.remove
使用 PyObject_RichCompareBool
函数来比较对象。此函数在开头包含以下内容:
/* Quick result when objects are the same.
Guarantees that identity implies equality. */
if (v == w) {
if (op == Py_EQ)
return 1;
else if (op == Py_NE)
return 0;
}
因此,它首先比较对象标识。仅当对象不同时,它才继续使用 ==
运算符。
在您的示例中,如果 x
是列表中的第一个对象,它将与删除的值是同一对象,因此被上述函数视为相等并被删除。如果第一个对象是其他对象,则将它与使用 ==
运算符的 x
进行比较,这将返回一个 numpy 数组并导致错误,因为它无法转换为布尔值。
in
运算符的工作方式相同,因此x in [x,1]
x in [1,x]
引发错误时返回True
。
错误第二次发生,因为使用 x
测试42
的标识失败,Python 回退到使用相等 (==
( 将x
与整数 42 进行比较。
mylist.remove(x)
摆脱了列表中第一次出现的x
,没有任何打嗝,因为x is x
返回True
。问题是,当第一个元素的第一个元素是 42 时,x is 42
返回False
所以 Python 会尝试x == 42
。
此相等性测试返回数组array([False, False, False])
。与本机 Python 对象不同,NumPy 数组具有不明确的真值,并且会引发错误。