PyYAML 3.12在不同操作系统下键遍历顺序差异原因咨询
为什么PyYAML 3.12在不同Python版本下遍历键的顺序不同?
这个差异的核心原因完全在于你使用的Python版本对字典有序性的实现不同,和PyYAML 3.12本身关系不大——PyYAML在这里只是直接复用了Python内置字典的行为。
让我具体拆解:
- Linux上的Python 3.4.8:这个版本的Python字典基于传统哈希表实现,不保证保留插入顺序。当PyYAML加载YAML映射时,它会把键值对存入普通字典,遍历的时候Python会按哈希值排序后返回键,所以你看到的是字母序的
function_a→function_b→function_c→function_d。 - Windows上的Python 3.6.5:虽然Python官方直到3.7才把「字典保留插入顺序」列为语言规范,但CPython 3.6的字典实现已经偷偷改成了能保留插入顺序的结构(这是CPython的一个优化特性,当时还不是标准)。所以PyYAML加载YAML后,字典会保留YAML文件里键的原始顺序,也就是你看到的
function_a→function_c→function_d→function_b。
如果你需要在所有Python版本下都保证遍历顺序和YAML文件一致,有个简单的解决办法:让PyYAML把映射加载为OrderedDict而不是普通字典。你可以自定义一个构造器来实现:
from collections import OrderedDict import yaml def ordered_yaml_load(stream): # 自定义构造器,把YAML映射转为OrderedDict def construct_ordered_mapping(loader, node): loader.flatten_mapping(node) return OrderedDict(loader.construct_pairs(node)) yaml.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_ordered_mapping) return yaml.load(stream) # 使用这个函数加载YAML with open('myyamlfile.yml') as fp: conf = ordered_yaml_load(fp) # 此时遍历conf['functions'],顺序会和YAML文件里完全一致 for function in conf['functions']: print(function)
另外提一句:PyYAML 5.1+版本开始支持直接通过yaml.load的Loader参数指定yaml.FullLoader,并且可以结合typ='ordered'来直接加载为有序字典,不过你用的是3.12版本,所以上面的自定义构造器方法更适合你。
内容的提问来源于stack exchange,提问作者brillenheini
相关产品推荐
相关产品推荐

