UserDict.popitem不是后进先出
请看下面的代码片段:
from collections import UserDict
class D(dict): ...
d = D(foo="bar", baz=42)
print(d.popitem()) # ('baz', 42)
class UD(UserDict): ...
ud = UD(foo="bar", baz=42)
print(ud.data) # {'foo': 'bar', 'baz': 42}
print(ud.popitem()) # ('foo', 'bar')
在 UserDict 实现中,顺序似乎如预期地被保持,因为它内部使用的是一个自Python 3.7起就已是有序的 data 字典。
为什么弹出的项是第一个而不是最后一个?我是不是理解错了?这是一个错误,还是一个特性?
在全新环境中测试了3.13.9和 3.14.0。
解决方案
UserDict 包装了一个字典,但它并没有继承 dict,甚至连 collections.OrderedDict 都不是子类。相反,它继承自 collections.abc.MutableMapping。因此,UserDict.popitem 不具备 dict.popitem 所具备的LIFO保证。在3.14及更早版本中,它改为使用 MutableMapping.popitem,该实现使用 dict.__iter__(因此是FIFO,只有在对值进行修改时才例外):
def popitem(self):
'''D.popitem() -> (k, v), remove and return some (key, value) pair
as a 2-tuple; but raise KeyError if D is empty.
'''
try:
key = next(iter(self))
except StopIteration:
raise KeyError from None
value = self[key]
del self[key]
return key, value
在3.15中,UserDict.popitem 将有一个 新的实现,它将保证与底层字典相同的删除顺序。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。