【问题标题】:Removal of an item from a python list, how are items compared (e.g. numpy arrays)?从 python 列表中删除一个项目,如何比较项目(例如 numpy 数组)?
【发布时间】:2015-04-18 04:59:54
【问题描述】:

我对python(2.7)list.remove函数有点疑惑。在documentation of remove 中它说:“从列表中删除值为 x 的第一项。如果没有这样的项,则会出错。”

所以,我想这里 value 意味着比较是基于 平等(即==)而不是身份(即@987654324 @)。但是,有人可以向我解释以下行为。显然,这两种比较都被使用了,但是以一种相当奇怪的方式:

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()

发生了什么事?

【问题讨论】:

    标签: python arrays list numpy equality


    【解决方案1】:

    看源码,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] 返回Truex in [1,x] 引发错误。

    【讨论】:

      【解决方案2】:

      该错误第二次发生,因为测试 42x 的身份失败,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 数组具有不明确的真值并引发错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-15
        • 1970-01-01
        • 2021-10-19
        • 2023-01-24
        • 2021-03-12
        • 2018-02-03
        • 2011-05-24
        • 2022-12-20
        相关资源
        最近更新 更多