Skip to main content
 首页 » 编程设计

python之以最佳方式从字典中删除所有值

2025年05月04日22softidea

我有一本像这样的字典:

z = {'d': '2018', 'uc': '609', 'bc': 'HSBC', 'ab': 'FICCL', .... } 

它有 57 个键值对。我想保留键但删除值并使它们成为空字符串,如“”。我尝试了以下代码:

for k,v in z.items(): 
    z[k] = "" 

我得到了想要的输出:

z = {'d': '', 'uc': '', 'bc': '', 'ab': '', .... } 

我想知道这是否是一次删除字典中所有值的最简单方法。还有别的办法吗?是否有任何内置功能可以执行此操作?有没有没有循环的单行?

请您参考如下方法:

如果您需要就地更新字典,您必须遍历键,所以您的方法是一个很好且可读的方法。它也比更新字典的其他方法更快,甚至比使用相同键创建新字典的方法更快!

您可以放弃 items() 调用,您对这些值不感兴趣。直接在字典上循环获取键:

for k in z: 
    z[k] = "" 

另一种方法是使用 dict.fromkeys()创建一个新的空字典。要更新现有字典就地(以便对同一字典的其他引用看到更改),您可以调用 z.update() 传入新字典:

# set all values to an empty string, in place 
z.update(dict.fromkeys(z, "")) 

缺点是您可能需要包含注释来解释该行应该实现的目标。它还较慢,因为正在创建一个新对象只是为了更新现有对象。此外,您要小心使用dict.fromkeys(),因为第二个参数是可重复用于所有键的单个值。如果您要使用像列表这样的可变值,这很重要。如果您只需要一个新 字典,您可以使用z.update() 并直接分配dict.fromkeys() 结果到 z。

假设您需要就地更新,快速比较性能差异:

>>> from timeit import Timer 
>>> testdict = {i: i for i in range(10 ** 6)} 
>>> def explicit_loop(d): 
...     d = d.copy() 
...     for k in d: 
...         d[k] = "" 
... 
>>> def dict_fromkeys(d): 
...     d = d.copy() 
...     d.update(dict.fromkeys(d, "")) 
... 
>>> def base_copy(d): 
...     d = d.copy() 
... 
>>> count, total = Timer("f(t)", "from __main__ import base_copy as f, testdict as t").autorange() 
>>> base_copy_time = total / count 
>>> for f in (explicit_loop, dict_fromkeys): 
...     count, total = Timer("f(t)", f"from __main__ import {f.__name__} as f, testdict as t").autorange() 
...     print(f"{f.__name__:>15}: {((total / count) - base_copy_time) * 1000:.2f} milliseconds") 
... 
  explicit_loop: 43.15 milliseconds 
  dict_fromkeys: 68.66 milliseconds 

请注意,为了便于准确测试,每次都需要复制输入字典,这就是为什么有一个 base_copy 测试来调整时间。

您可以看到,z 上的显式循环显然是赢家。但是,即使您不需要就地更新字典,使用 dict.fromkeys() 也比就地更新 z 慢!

就地更新不必动态调整字典大小以适应任意数量的键,也不需要创建新对象:

>>> def dict_fromkeys_no_update(d): 
...     d = d.copy()  # to keep comparisons fair, copy only needed for the loop case 
...     d = dict.fromkeys(d, "") 
... 
>>> for f in (explicit_loop, dict_fromkeys_no_update): 
...     count, total = Timer("f(t)", f"from __main__ import {f.__name__} as f, testdict as t").autorange() 
...     print(f"{f.__name__:>25}: {((total / count) - base_copy_time) * 1000:.2f} milliseconds") 
... 
            explicit_loop: 41.27 milliseconds 
  dict_fromkeys_no_update: 54.78 milliseconds 

因此,无论您是否需要新字典或就地更新,只需对现有字典键进行简单的 Python 循环就是无可争议的赢家。