当我尝试从列表中删除元素时,如何忽略ValueError?

Jua*_*blo 41 python error-handling list elements

如果我在列表中不存在a.remove(x)时调用,如何忽略"not in list"错误消息?xa

这是我的情况:

>>> a = range(10)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a.remove(10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
>>> a.remove(9)
Run Code Online (Sandbox Code Playgroud)

Nik*_* B. 42

一个好的,线程安全的方法是尝试它并忽略异常:

try:
    a.remove(10)
except ValueError:
    pass  # do nothing!
Run Code Online (Sandbox Code Playgroud)


g.d*_*d.c 32

只要元素的顺序不一定重要,我个人会考虑使用a set而不是a list.然后你可以使用discard方法:

>>> S = set(range(10))
>>> S
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> S.remove(10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 10
>>> S.discard(10)
>>> S
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Run Code Online (Sandbox Code Playgroud)

  • 在不合适的情况下使用 `set` 可能会产生意想不到的后果。从文档中,[`从列表中删除值为 x 的第一项。如果没有这样的项目,这是一个错误。`](http://docs.python.org/2/tutorial/datastructures.html) OP 可能只想删除其他用例中的第一个项目,表明其中的有效重复项列表。 (3认同)

ret*_*ian 17

作为忽略ValueError的替代方法

try:
    a.remove(10)
except ValueError:
    pass  # do nothing!
Run Code Online (Sandbox Code Playgroud)

我认为以下内容更直接,更易读:

if 10 in a:
    a.remove(10)
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的想法,但正如@Niklas B.指出的那样,他是"线程安全的",因为无论如何,10不存在只会导致*被捕*异常.在这个答案中,在被检查的`if`条件和被调用的`.remove()之间可以从`a`中删除`10`,导致*uncaught*`ValueError`.(如果你可以保证'a`没有被其他任何东西修改,那么这很好,但是接受了答案,你甚至不必考虑这种可能性.) (7认同)
  • 有点撕裂这个...你在什么时候放弃了[禅宗的禅](https://www.python.org/dev/peps/pep-0020/)的线程安全?当然,如果您正在编写可能在多线程应用程序中使用的库模块,您将需要使事情变得更复杂和/或记录其线程安全性(或缺少它),但是一般应该尝试这样做吗? (4认同)
  • 对于 lambda 表达式,有时出于相同目的使用单行代码会很有帮助,在这种情况下,`a in 10 and a.remove(10)` 就可以完成这项工作。虽然它也不是线程安全的。 (2认同)
  • 如果您关心线程安全,您应该使用显式锁定。 (2认同)

Phi*_*l S 7

当我只关心确保条目不在列表、字典或集合中时,我使用 contextlib,如下所示:

import contextlib

some_list = []
with contextlib.suppress(ValueError):
    some_list.remove(10)

some_set = set()
some_dict = dict()
with contextlib.suppress(KeyError):
    some_set.remove('some_value')
    del some_dict['some_key']
Run Code Online (Sandbox Code Playgroud)


JJL*_*JJL 5

列表理解如何?

a = [x for x in a if x != 10]
Run Code Online (Sandbox Code Playgroud)

  • @Melvyn,我主要将其作为替代方案提供,不一定是“改进”。我喜欢它只有一行并且可读。 (3认同)
  • 这会创建一个新列表,这比修改现有列表效率低,尤其是在未找到该项目并且不需要复制元素的情况下。 (2认同)