从 python 列表中删除项目,如何比较项目(例如 numpy 数组)



我对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 数组具有不明确的真值,并且会引发错误。

相关内容

最新更新