我正在计算同一备份文件中某些对象的出现:

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开始,字典顺序得以保留,因此不会发生此问题。

就是说,由于某些值会覆盖其他值,因此程序会出现概念错误,因为您没有使用所有数据,并且无法控制要使用的部分以及要丢弃的部分。

08-25 08:48
查看更多