我正在计算同一备份文件中某些对象的出现:
with open(file_path, encoding='utf-8') as data:
backend_data = json.load(data)
users = {}
sessions = {}
for key in backend_data.keys():
users.update(backend_data[key]['users'])
for key, value in users.items():
if 'session' in value:
sessions.update(value['session'])
print(len(users))
print(len(sessions))
虽然我总是为用户得到相同的
len
结果,但是每次调用脚本时,会话的len
几乎都不同。该文件位于我的硬盘驱动器上,在运行期间未做任何更改。以下是5次运行的一些示例结果:
// 1.
users: 819
sessions: 2373
// 2.
users: 819
sessions: 1995
// 3.
users: 819
sessions: 2340
// 4.
users: 819
sessions: 2340
// 5.
users: 819
sessions: 2069
有关该文件的一些其他信息:它的长度为34535行,大小为959kb。
当我多次运行脚本时,为什么在一个词典中获得不同的值,而在另一词典中却获得不同的值?
最佳答案
我可能对发生的事情有所了解:
由于您要使用自然顺序来迭代字典,因此无法保证字典的顺序,因此更新时可能会有一些讨厌的副作用。
在运行之间,由于哈希种子(默认情况下是随机的),顺序可以更改(请参见Why items order in a dictionary changed in Python?)。backend_data[key]['users']
是一本字典,可能有一些键作为列表。根据顺序,某些列表会被其他列表覆盖,或者反过来,这不会更改第一个字典的长度。
但是,当您迭代值(第二个循环)时,第二个字典中可能会输入不同的数据。
要修复它,您必须对可迭代对象进行排序:
with open(file_path, encoding='utf-8') as data:
backend_data = json.load(data)
users = {}
sessions = {}
for key,bd in sorted(backend_data.items()):
users.update(bd['users'])
for key, value in sorted(users.items()):
if 'session' in value:
sessions.update(value['session'])
(请注意第一个循环的略微优化:不访问键,可以使用
items()
并在元组上进行排序,这与对键进行排序相同)请注意,从Python 3.6开始,字典顺序得以保留,因此不会发生此问题。
就是说,由于某些值会覆盖其他值,因此程序会出现概念错误,因为您没有使用所有数据,并且无法控制要使用的部分以及要丢弃的部分。