在Python编程中,字典是一种以键值对形式存储数据的结构。从Python3.7开始字典会保持插入顺序,但这并不代表字典自身具备排序能力。当我们需要按照特定规则排列字典内容时,必须借助外部函数或额外数据结构来完成。

为什么字典不能直接排序
很多初学者会尝试对字典对象直接调用sort方法,结果抛出AttributeError,因为dict类型并没有定义sort函数。字典的本质是哈希表,其设计目标是实现O(1)级别的查找效率,而不是维护有序状态。即便现代Python版本保留了元素的插入次序,这种次序也仅仅是记录写入顺序,并不是按照大小或字母规则排列。
如果业务逻辑要求按某种规律输出字典数据,例如把用户信息按年龄从大到小打印,我们就必须把字典转换成可排序的序列。常见的做法是将字典的键、值或键值对提取出来,放到列表里,再使用排序函数处理。这样既不破坏原字典的查询性能,也能满足展示或导出的顺序需求。
使用sorted函数按 key 排序
sorted是Python内置的高阶函数,它接受任何可迭代对象并返回一个新的已排序列表。对于字典,默认传入字典本身会得到排好序的键列表。我们可以在key参数里用lambda指明排序依据,比如直接取键,或者取字典对应的值。
下面示例演示如何按字典的键进行升序排列,并用推导式生成新字典:
# 原始无序字典
data = {'banana': 3, 'apple': 1, 'cherry': 2}
# 按 key 升序排列,返回排好序的键
sorted_keys = sorted(data)
print(sorted_keys) # ['apple', 'banana', 'cherry']
# 生成排序后的新字典
sorted_by_key = {k: data[k] for k in sorted_keys}
print(sorted_by_key) # {'apple': 1, 'banana': 3, 'cherry': 2}
这种写法清晰直观,适合键为字符串或数字且只需单层排序的场景。如果键是中文,sorted默认按Unicode编码排序,若需要拼音顺序则要引入第三方库如pypinyin来构造key函数。
按 value 排序的几种方式
实际开发中更常见的是按值排序,例如统计词频后找出出现次数最多的词。此时应把字典的items方法得到的键值元组传给sorted,并在key中指定取索引为1的元素。
以下代码展示按值升序和降序两种写法:
score = {'张三': 88, '李四': 75, '王五': 92}
# 按值升序
asc = sorted(score.items(), key=lambda x: x[1])
print(asc) # [('李四', 75), ('张三', 88), ('王五', 92)]
# 按值降序
desc = sorted(score.items(), key=lambda x: x[1], reverse=True)
print(desc) # [('王五', 92), ('张三', 88), ('李四', 75)]
# 转回字典
sorted_dict = dict(desc)
print(sorted_dict)
使用items方法可以同时拿到键和值,lambda x: x[1]表示用元组第二个元素即值参与比较。reverse参数控制方向,默认为False即升序。转换回字典时注意,Python3.7以上会保留这个由排序产生的插入顺序,因此可以直接用dict构造器。
多重条件排序与复杂对象
当值本身也是复合结构,或者需要先按值再按键排序时,可以在key里返回元组。Python的排序是稳定的,并且元组比较会依次进行,这让我们能优雅地表达多重规则。
看一个先按分数降序、分数相同再按名字升序的例子:
records = {
'zhao': {'age': 20, 'score': 90},
'qian': {'age': 19, 'score': 90},
'sun': {'age': 21, 'score': 85}
}
# 按 score 降序、key 升序
result = sorted(records.items(),
key=lambda x: (-x[1]['score'], x[0]))
print(result)
# [('qian', ...), ('zhao', ...), ('sun', ...)]
这里用负号实现数值降序,而字符串键保持默认升序。对于不支持取负的类型,可以写两个sorted嵌套,或者统一在key里返回元组并用reverse配合。复杂对象排序的核心就是设计一个能反映优先级顺序的key函数。
使用OrderedDict的场景
在早期Python版本中,普通字典不保证顺序,如果需要一个“记住”排序结果的字典类型,可以使用collections.OrderedDict。虽然现在普通字典已具备顺序特性,但OrderedDict在需要明确语义或兼容老代码时仍有价值。
示例展示如何构造排序后的OrderedDict:
from collections import OrderedDict
plain = {'b': 2, 'a': 1, 'c': 3}
ordered = OrderedDict(sorted(plain.items()))
print(ordered) # OrderedDict([('a', 1), ('b', 2), ('c', 3)])
OrderedDict提供了move_to_end等专属方法,方便动态调整顺序。如果只是临时输出排序结果,直接用sorted加推导式更轻量;若要在整个程序生命周期里维持顺序并做顺序相关操作,则OrderedDict更合适。
小结与选择建议
对字典排序并不神秘,核心工具就是sorted函数与key参数。按key排序直接传字典或keys;按value排序用items加lambda取元组第二项;多重条件依靠返回元组来实现。生成新字典可用推导式或dict构造器,老版本环境可换用OrderedDict。
在写代码时,应避免修改原字典的冲动,保持函数无副作用。同时要留意中文、大小写、None值等边界情况,在key函数里做好预处理,才能让排序结果符合业务预期。