You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python3.7+如何按顺序访问字典元素?

Python 3.7+ 有序字典的顺序利用问题及LFU缓存实现方案

问题描述

我了解自Python 3.7起字典是有序的,但文档似乎未列出利用该顺序的方法。比如如何不依赖键按顺序访问字典的第一个元素?有序字典可执行哪些操作?

举例来说,我正在实现LFU(最近最少使用)缓存,不仅需要跟踪键的使用次数,还要用LRU(最近最少使用)信息作为平局决胜条件。我可以用字典嵌套队列实现优先队列,但会失去队列内的O(1)查找能力。若使用字典嵌套字典,既能保留哈希集合的优势,又能实现优先队列……我认为是可行的。我只需要能弹出字典的第一个元素,但遗憾的是没有dict.popleft()方法。

目前我将键转换为列表并使用列表的第一个元素,这确实有效(字典会维持顺序),但转换成本较高。

LFU_queue = collections.defaultdict(collections.defaultdict)
LFU_queue[1].update({"key_1":None})
LFU_queue[1].update({"key_32":None})
LFU_queue[1].update({"key_6":None})

# 查看该结构,得到预期的有序嵌套字典:
# { 1: {"key_1":None, "key_32":None, "key_6":None}}

# 我希望能执行类似这样的操作
# LFU_queue[1].popleft() 以返回 {"key_1":None}

list(LFU_queue[1])[0] 可行,但不够理想

解决方案说明

1. 高效访问/弹出字典首个元素的方法

Python 3.7+ 的普通字典确实保留插入顺序,但没有直接提供popleft()方法。如果不想承担转列表的O(n)成本,可以用以下O(1)级别的操作:

  • 获取首个键:用next(iter(dict))直接获取字典迭代器的第一个元素,比如next(iter(LFU_queue[1]))就能拿到key_1,再通过键取值即可。
  • 弹出首个元素:结合迭代器和pop()方法:
    inner_dict = LFU_queue[1]
    first_key = next(iter(inner_dict))
    first_item = {first_key: inner_dict.pop(first_key)}
    # 此时first_item就是{"key_1": None},且该元素已从inner_dict中移除
    

2. 有序字典的可用操作

对于Python 3.7+的普通有序字典,除常规字典操作外,还能基于顺序做这些事:

  • 用for k, v in dict.items()按插入顺序遍历键值对
  • 用reversed(dict)按逆插入顺序迭代键(Python 3.8及以上支持)
  • 用next(iter(dict))和next(reversed(dict))快速获取首尾键

如果需要更专业的顺序操作(比如直接弹出首尾、移动元素位置),建议使用collections.OrderedDict,它专门提供了这类方法:

from collections import OrderedDict

od = OrderedDict([("key_1", None), ("key_32", None), ("key_6", None)])
first_item = od.popitem(last=False)  # 弹出第一个元素,返回("key_1", None)
od.move_to_end("key_32")  # 将指定键移到字典末尾

3. LFU缓存实现的优化建议

你的嵌套字典思路完全可行:外层字典记录使用次数,内层有序字典按LRU顺序存储同次数的键。如果用普通字典,就用next(iter(inner_dict))获取最久未使用的键;如果追求代码简洁和操作直观,内层换成OrderedDict会更方便,直接调用popitem(last=False)就能弹出LRU元素,同时保持O(1)的查找效率。

内容的提问来源于stack exchange,提问作者Mister Nibbles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 01:05:26