使用defaultDict等默认值初始化OrderedDict中不存在的键



是否有任何方法可以使用默认值访问OrderedDict中不存在的键,就像我们在defaultDict 中所做的那样

Ex.
od = OrderedDict({'a':1})
print(od['b'])  # Output: KeyError: 'b'

这是KeyError在以下实现中抛出的真正问题

l =['a','b','c','b']
od = OrderedDict({})
for k in l:
od[k] += 1 # KeyError

这种实施方式有意避免

for k in l:
if k in od:
od[k] += 1
else:
od[k] = 1

只需从OrderedDict继承并重新定义__getitem__:

from collections import OrderedDict

class OrderedDictFailFree(OrderedDict):
def __getitem__(self, name):
try:
return OrderedDict.__getitem__(self, name)
except KeyError:
return None

od = OrderedDictFailFree({'a': 1})
print(od['b'])
正如Yevgeniy Kosmak的回答所示,这当然是可行的。然而,请记住,在Python中>3.7(或者甚至>=3.6,只要您使用默认的CPython实现(,所有字典现在都保持插入顺序。因此,如果您不需要与旧版本兼容,并且只需要维护秩序的密钥,那么您可能根本不需要OrderedDictdefaultdict也将维持其秩序。

然而,OrderedDictdict/defaultdict之间仍然存在一些差异,这可能会也可能不会影响您的用例。其中包括:

  • 两个OrderedDict之间的相等性检查不仅检查键/值,还检查顺序。(对于两个defaultdict或对照defaultdict检查的OrderedDict,情况并非如此。(
  • OrderedDictmove_to_end()方法可以有效地将键/值对移动到前端或末端
  • OrderedDictpopitem()方法可以选择性地弹出并返回第一个键/值,而不是最后一个。(dictpopitem()返回最后插入的键/值,或者,在3.7之前,返回任意对。(
  • 在3.8之前,dict/defaultdict不直接支持反向迭代,例如使用reversed()。然而,在3.6或3.7中,您仍然可以通过中间列表或元组来实现这一点

注意:即使dict现在复制了OrderedDict的所有功能,后者可能仍然不会从Python中删除。现有的旧程序已经使用OrderedDict,Python通常不会用新的次要版本(例如3.6到3.7(破坏现有代码,除非有令人信服的原因,比如在语法中添加新的关键字。有关Python版本控制系统的更多信息,请参阅此处,特别是有关向后兼容性的详细信息,请参见此处。

我们似乎可以使用od.setdefault('b',0),尽管它不是一个优雅的解决方案。

od = OrderedDict({'a':1})
print(od.setdefault('b',0)) # od.get('b',0) could be used if intention is not to change od
l =['a','b','c','b','b']
od = OrderedDict({})
for k in l:   
od[k] = od.setdefault(k,0) + 1 # set key to 0 if there in no key k and increment by 1