【问题标题】:How can I remove a key from a Python dictionary?如何从 Python 字典中删除键?
【发布时间】:2012-07-01 21:48:31
【问题描述】:

从字典中删除键时,我使用:

if 'key' in my_dict:
    del my_dict['key']

有没有一种方法可以做到这一点?

【问题讨论】:

标签: python dictionary data-structures unset


【解决方案1】:

要删除一个键,不管它是否在字典中,使用dict.pop()的两个参数形式:

my_dict.pop('key', None)

如果字典中存在key,则返回my_dict[key],否则返回None。如果未指定第二个参数(即my_dict.pop('key'))且key 不存在,则会引发KeyError

要删除一个保证存在的键,也可以使用:

del my_dict['key']

如果键不在字典中,这将引发KeyError

【讨论】:

  • 有时使用pop() 优于del 的优势:它返回该键的值。这样,您可以在一行代码中从字典中获取和删除条目。
  • 在问题中不需要保留值。这只会增加不必要的复杂性。 @zigg(下)的答案要好得多。
  • @SalvatoreCosentino 我无法理解你的论点。这个答案中的代码比另一个答案中的代码复杂吗?
  • @SalvatoreCosentino 不,忽略函数的返回值一点也不低效。恰恰相反——如果密钥不存在,这个解决方案比try/except 解决方案快得多。您可能会发现其中一个或另一个更易于阅读,这很好。两者都是惯用的 Python,因此请选择您喜欢的任何内容。但是声称这个答案更复杂或更低效是没有意义的。
  • @user5359531 我不明白。这是怎么回事? Python 内置类型的所有方法都没有返回self,所以如果这个方法返回,那就太令人惊讶了。
【解决方案2】:

专门回答“有没有一种方法可以做到这一点?”

if 'key' in my_dict: del my_dict['key']

...嗯,你 ;-)

不过,您应该考虑,这种从dict 中删除对象的方式是not atomic——'key' 可能在my_dict 中出现在if 语句中,但可能会被删除在执行del 之前,在这种情况下del 将失败并返回KeyError。鉴于此,use dict.pop 或类似

的东西是最安全的
try:
    del my_dict['key']
except KeyError:
    pass

当然,这绝对是不是单行的。

【讨论】:

  • 是的,pop 绝对更简洁,尽管这样做有一个关键优势:它在做什么会立即清晰。
  • try/except 语句更昂贵。引发异常很慢。
  • @ChrisBarker 我发现如果密钥存在,try 会稍微快一些,但如果不存在,try 确实会慢很多。 pop 相当一致,但比除try 之外的所有密钥都慢。见gist.github.com/zigg/6280653。最终,这取决于您期望密钥实际出现在字典中的频率,以及您是否需要原子性——当然,还取决于您是否进行过早优化;)
  • 我认为不应该忽视清晰的价值。为此 +1。
  • 关于try/except的费用,你也可以去if 'key' in mydict: #then del...。我需要从 dict 中提取一个 key/val 才能正确解析,pop 不是一个完美的解决方案。
【解决方案3】:

我花了一些时间才弄清楚my_dict.pop("key", None) 到底在做什么。因此,我将添加此作为答案以节省其他人的谷歌搜索时间:

pop(key[, default])

如果 key 在字典中,删除它并返回它的值,否则 返回默认。如果 default 没有给出并且 key 不在 字典,一个KeyError 被提出。

Documentation

【讨论】:

  • 在python解释器中输入help(dict.pop)即可。
  • help() 和 dir() 可以成为你的朋友,当你需要知道某事是做什么的时候。
  • 或 IPython 中的 dict.pop?
【解决方案4】:

del my_dict[key]my_dict.pop(key) 在键存在时从字典中删除键稍快

>>> import timeit
>>> setup = "d = {i: i for i in range(100000)}"

>>> timeit.timeit("del d[3]", setup=setup, number=1)
1.79e-06
>>> timeit.timeit("d.pop(3)", setup=setup, number=1)
2.09e-06
>>> timeit.timeit("d2 = {key: val for key, val in d.items() if key != 3}", setup=setup, number=1)
0.00786

但是当密钥不存在时if key in my_dict: del my_dict[key]my_dict.pop(key, None) 稍快。在try/except 语句中,两者都至少比del 快三倍:

>>> timeit.timeit("if 'missing key' in d: del d['missing key']", setup=setup)
0.0229
>>> timeit.timeit("d.pop('missing key', None)", setup=setup)
0.0426
>>> try_except = """
... try:
...     del d['missing key']
... except KeyError:
...     pass
... """
>>> timeit.timeit(try_except, setup=setup)
0.133

【讨论】:

  • @Boris - 作为一般练习很有用。
  • @daisy 我的意思是你应该选择最易读的语法而不是快 300 纳秒的操作(这实际上是第一组中 delpop 之间的区别以上时间)
  • 而且这些操作非常快,以至于这些时间都不可靠。
【解决方案5】:

如果您需要在一行代码中从字典中删除很多键,我认为使用 map() 非常简洁且 Python 可读:

myDict = {'a':1,'b':2,'c':3,'d':4}
map(myDict.pop, ['a','c']) # The list of keys to remove
>>> myDict
{'b': 2, 'd': 4}

如果您需要捕获弹出字典中没有的值的错误,请在 map() 中使用 lambda,如下所示:

map(lambda x: myDict.pop(x,None), ['a', 'c', 'e'])
[1, 3, None] # pop returns
>>> myDict
{'b': 2, 'd': 4}

或在python3 中,您必须改用列表推导:

[myDict.pop(x, None) for x in ['a', 'c', 'e']]

它有效。即使 myDict 没有“e”键,“e”也不会导致错误。

【讨论】:

  • 这在 Python 3 中不起作用,因为 map 和朋友现在很懒惰并返回迭代器。使用map 处理副作用通常被认为是不好的做法;一个标准的for ... in 循环会更好。请参阅Views And Iterators Instead Of Lists 了解更多信息。
  • 不管品味和实践风格如何,列表推导在 Py3 [myDict.pop(i, None) for i in ['a', 'c']] 中仍然可以工作,因为它们提供了 map(和 filter)的一般替代方案。
  • @MichaelEkoka 你不应该使用列表推导来解决它们的副作用,使用常规的for ... in 循环。
  • @Boris 你可能是对的。我的回答特别与使用 map() 有关,因为它的副作用经常被使用。 Python 中推荐的替代方法是 列表推导式,在我看来,它仍然是非常易读的,并且在认知上作为一个单行词(见问题)。仅用于它们的副作用,这两种结构确实会导致一个无用的列表,这可能是低效的。从 Python3 开始,我不知道有一个内置函数可以安全优雅地迭代生成器表达式,而不会产生代价高昂的副产品,例如loop(d.pop(k) for k in ['a', 'b']).
  • @MichaelEkoka “内置函数”是一个 for 循环:for k in ['a', 'b']: d.pop(k)。为什么你需要一种不同的方式来做到这一点?如果您需要它只占用一行那么严重,那么您可以将 for 循环的第二部分放在同一行。
【解决方案6】:

您可以使用dictionary comprehension 创建一个删除该键的新字典:

>>> my_dict = {k: v for k, v in my_dict.items() if k != 'key'}

您可以按条件删除。如果key 不存在,则不会出错。

【讨论】:

  • 这个答案与其他答案不同,因为它没有副作用(它不会改变原始字典)。
  • 虽然我可能也会这样做,但这会在内存中创建一个全新的字典,将对象复制(引用)到新字典。然后将其保存为旧名称。对于大型词典,这可能需要一些时间。 del dict[key]dict.pop(key) 在所有情况下都会更快。
【解决方案7】:

使用“del”关键字:

del dict[key]

【讨论】:

    【解决方案8】:

    我们可以通过以下一些方法从 Python 字典中删除一个键。

    使用del 关键字;不过,这与您所做的几乎相同 -

     myDict = {'one': 100, 'two': 200, 'three': 300 }
     print(myDict)  # {'one': 100, 'two': 200, 'three': 300}
     if myDict.get('one') : del myDict['one']
     print(myDict)  # {'two': 200, 'three': 300}
    

    或者

    我们可以这样做:

    但请记住,在此过程中,实际上它不会删除字典中的任何键,而是从该字典中排除特定键。此外,我观察到它返回的字典与myDict 的排序不同。

    myDict = {'one': 100, 'two': 200, 'three': 300, 'four': 400, 'five': 500}
    {key:value for key, value in myDict.items() if key != 'one'}
    

    如果我们在 shell 中运行它,它会执行类似{'five': 500, 'four': 400, 'three': 300, 'two': 200} 的东西——注意它与myDict 的顺序不同。同样,如果我们尝试打印myDict,那么我们可以看到所有键,包括我们通过这种方法从字典中排除的键。但是,我们可以通过将以下语句分配给变量来创建一个新字典:

    var = {key:value for key, value in myDict.items() if key != 'one'}
    

    现在如果我们尝试打印它,那么它将遵循父顺序:

    print(var) # {'two': 200, 'three': 300, 'four': 400, 'five': 500}
    

    或者

    使用pop() 方法。

    myDict = {'one': 100, 'two': 200, 'three': 300}
    print(myDict)
    
    if myDict.get('one') : myDict.pop('one')
    print(myDict)  # {'two': 200, 'three': 300}
    

    delpop 的区别在于,使用pop() 方法,如果需要,我们实际上可以存储键的值,如下所示:

    myDict = {'one': 100, 'two': 200, 'three': 300}
    if myDict.get('one') : var = myDict.pop('one')
    print(myDict) # {'two': 200, 'three': 300}
    print(var)    # 100
    

    fork this gist 以供将来参考,如果您觉得这很有用。

    【讨论】:

    • 不要使用if myDict.get('one') 来检查密钥是否存在!如果 myDict['one'] 有一个错误的值,它会失败。此外,dicts 没有固有的顺序,因此提及它是没有意义的。
    • @Rob 字典按插入顺序排序,从 CPython 3.6 开始,所有其他 Python 实现从 3.7 开始。
    【解决方案9】:

    如果你想非常冗长,你可以使用异常处理:

    try: 
        del dict[key]
    
    except KeyError: pass
    

    但是,如果密钥不存在,这将比 pop() 方法慢。

    my_dict.pop('key', None)
    

    几个键没关系,但如果你反复这样做,那么后一种方法是更好的选择。

    最快的方法是这样的:

    if 'key' in dict: 
        del myDict['key']
    

    但是这种方法很危险,因为如果在两行之间删除'key',则会引发KeyError

    【讨论】:

      【解决方案10】:

      Dictionary 数据类型有一个名为 dict_name.pop(item) 的方法,可用于从字典中删除 key:value 对。

      a={9:4,2:3,4:2,1:3}
      a.pop(9)
      print(a)
      

      这将给出如下输出:

      {2: 3, 4: 2, 1: 3}
      

      这样你可以在一行中从字典中删除一个项目。

      【讨论】:

        【解决方案11】:

        另一种方法是使用 items() + dict理解。

        items() 结合dict理解也可以帮助我们完成键值对删除的任务,但它的缺点是不是一个到位的dict技术。实际上,如果创建了一个新的字典,除了我们不希望包含的键。

        test_dict = {"sai" : 22, "kiran" : 21, "vinod" : 21, "sangam" : 21}
        
        # Printing dictionary before removal
        print ("dictionary before performing remove is : " + str(test_dict))
        
        # Using items() + dict comprehension to remove a dict. pair
        # removes  vinod
        new_dict = {key:val for key, val in test_dict.items() if key != 'vinod'}
        
        # Printing dictionary after removal
        print ("dictionary after remove is : " + str(new_dict))
        

        输出:

        dictionary before performing remove is : {'sai': 22, 'kiran': 21, 'vinod': 21, 'sangam': 21}
        dictionary after remove is : {'sai': 22, 'kiran': 21, 'sangam': 21}
        

        【讨论】:

        • 这实际上并没有做所要求的 - 它创建了一个新的字典,删除了不需要的键。此外,遍历所有键以删除一个键是在 O(N) 时间内执行 O(1) 操作。
        【解决方案12】:

        我更喜欢不可变的版本

        foo = {
            1:1,
            2:2,
            3:3
        }
        removeKeys = [1,2]
        def woKeys(dct, keyIter):
            return {
                k:v
                for k,v in dct.items() if k not in keyIter
            }
        
        >>> print(woKeys(foo, removeKeys))
        {3: 3}
        >>> print(foo)
        {1: 1, 2: 2, 3: 3}
        

        【讨论】:

          【解决方案13】:

          键上的单个过滤器

          • 如果 my_dict 中存在“key”,则返回“key”并将其从 my_dict 中删除
          • 如果 my_dict 中不存在“key”,则返回 None

          这将在原地更改my_dict(可变)

          my_dict.pop('key', None)
          

          按键上的多个过滤器

          生成一个新的字典(不可变)

          dic1 = {
              "x":1,
              "y": 2,
              "z": 3
          }
          
          def func1(item):
              return  item[0]!= "x" and item[0] != "y"
          
          print(
              dict(
                  filter(
                      lambda item: item[0] != "x" and item[0] != "y", 
                      dic1.items()
                      )
              )
          )
          

          【讨论】:

            【解决方案14】:

            您也可以将filterlambda 一起使用:

            >>> d = {'a': 1, 'b': 2, 'c': 3}
            >>> dict(filter(lambda x: x[0] != 'a', d.items()))
            {'b': 2, 'c': 3}
            >>>
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-11-18
              • 1970-01-01
              • 1970-01-01
              • 2020-03-11
              • 1970-01-01
              • 2014-09-02
              相关资源
              最近更新 更多