更新6/8/17
虽然过了3年,但我的PR仍然是一个临时解决方案,通过强制执行输出顺序。 Stream-Framework可能会重新考虑其使用内容作为通知密钥的设计。 GitHub Issue #153引用了这一点。
问题
见以下样本:
import pickle
x = {'order_number': 'X', 'deal_url': 'J'}
pickle.dumps(x)
pickle.dumps(pickle.loads(pickle.dumps(x)))
pickle.dumps(pickle.loads(pickle.dumps(pickle.loads(pickle.dumps(x)))))
结果:
(dp0\nS'deal_url'\np1\nS'J'\np2\nsS'order_number'\np3\nS'X'\np4\ns.
(dp0\nS'order_number'\np1\nS'X'\np2\nsS'deal_url'\np3\nS'J'\np4\ns.
(dp0\nS'deal_url'\np1\nS'J'\np2\nsS'order_number'\np3\nS'X'\np4\ns.
显然,每个转储的序列化输出都会发生变化。当我从任何键中删除一个字符时,这不会发生。我发现这是Stream-Framework使用pickle输出作为在其k / v商店存储通知的密钥。如果我们更好地了解这里发生了什么,我会提出请求。我找到了两种防止它的解决方案:
A - 排序后转换为字典(是的,以某种方式提供预期的副作用)
import operator
sorted_x = dict(sorted(x.iteritems(), key=operator.itemgetter(1)))
B - 删除下划线(但不确定这是否总是有效)
那么是什么导致了词典排序下的谜团?
证明调用sort over dict提供转储以产生相同的结果:
import operator
x = dict(sorted(x.iteritems(), key=operator.itemgetter(1)))
pickle.dumps(x)
"(dp0\nS'order_number'\np1\nS'X'\np2\nsS'deal_url'\np3\nS'J'\np4\ns."
x = pickle.loads(pickle.dumps(x))
x = dict(sorted(x.iteritems(), key=operator.itemgetter(1)))
pickle.dumps(x)
"(dp0\nS'order_number'\np1\nS'X'\np2\nsS'deal_url'\np3\nS'J'\np4\ns."
答案 0 :(得分:4)
字典是未排序的数据结构。这意味着订单是任意的,而pickle将按原样存储它们。如果要使用排序字典,可以使用collections.OrderedDict
。
当你在翻译中玩游戏时,你认为你看到的任何顺序都只是和你一起玩的翻译。
来自dict
的文档:
最好将字典视为一组无序的键:值对,并要求键是唯一的(在一个字典中)
请记住,dict.keys()
,dict.values()
和dict.items()
函数也会以任意顺序返回各自的值。