PEP 3106推荐的字典转列表方式为何更慢?性能疑问
为什么PEP 3106推荐的
list(d.values())比[*d.values()]慢? 这问题问得特别好!我来帮你理清楚背后的原因——其实这里涉及到PEP的历史背景和Python底层实现的优化差异:
PEP 3106的历史语境
PEP 3106是Python 3早期制定的规范,核心目标是把字典的values()、keys()、items()从返回完整列表改成返回视图对象(避免不必要的内存占用,视图会实时反映字典的变化)。当时推荐list(d.values()),是因为这是最直观的“将可迭代视图转换为列表”的写法,同时也契合Python 2到Python 3的迁移逻辑(Python 2中d.values()直接返回列表,Python 3需要套一层list()才能得到列表)。
但要注意:PEP 3106制定时,Python 3.5才刚引入可迭代对象解包语法([*iterable]),所以这份PEP自然不会把这种当时还很新的语法纳入推荐范围。
两种写法的底层效率差异
你的测试结果反映了Python对两种写法的不同优化逻辑:
list(d.values()):list构造函数的通用逻辑是先获取可迭代对象的迭代器,再逐个迭代元素并添加到列表中。即使dict_values视图本身知道自己的长度(有__len__方法),你用的Python 3.6版本中,list构造函数并没有利用这个信息预分配列表空间,导致列表在添加元素时需要多次扩容(内存不够就翻倍),额外消耗了时间。[*d.values()]:这种解包语法在Python 3.5+的实现中,会先检查可迭代对象是否支持__len__方法(dict_values正好支持),然后直接预分配对应长度的列表空间,再批量复制元素进去,完全避免了多次扩容的开销,所以速度更快。
关于编码规范的补充
虽然PEP 3106推荐list()写法,但随着Python版本迭代,[*d.values()]已经成为被广泛接受的简洁写法,而且完全符合PEP 8“可读性优先”的原则——它一眼就能看出是将可迭代对象转换为列表,代码更短也更直观。如果你的项目环境都是Python 3.5及以上,用解包写法完全没问题,既高效又契合现代Python的编码习惯。
内容的提问来源于stack exchange,提问作者d4tm4x
相关产品推荐
相关产品推荐

