使用生成器时如何使字典保持最新?

时间:2017-11-02 07:49:34

标签: python dictionary generator

当我使用生成器时,即使我修改传递给它的字典,生成器仍然会给我一个旧数据结构的结果。 我怎么能解决这个问题?

def min_key_order(adict:dict):
    for key, value in sorted(adict.items()):
        yield (key, value)

d = {1:'a', 2:'x', 4:'m', 8:'d', 16:'f'}
i = min_key_order(d)
print(next(i))
d.pop(2)
print(next(i))

它给了我(1,'a')(2,'x'),即使我从字典中弹出了密钥2。

1 个答案:

答案 0 :(得分:2)

您的生成器没有迭代字典。它正在迭代sorted()返回的新列表对象:

>>> d = {1:'a', 2:'x', 4:'m', 8:'d', 16:'f'}
>>> l = sorted(d.items())
>>> d
{1: 'a', 2: 'x', 4: 'm', 8: 'd', 16: 'f'}
>>> l
[(1, 'a'), (2, 'x'), (4, 'm'), (8, 'd'), (16, 'f')]
>>> d.pop(2)
'x'
>>> l
[(1, 'a'), (2, 'x'), (4, 'm'), (8, 'd'), (16, 'f')]

从字典中删除项目无法更新新列表;该结构不是字典上的实时视图。

要实现这一点,您必须每次迭代重新排序字典,并跟踪迭代位置:

def sorted_view(d):
    pos = 0
    while pos < len(d):
        yield sorted(d.items())[pos]
        pos += 1

这非常低效;分拣是一种相对昂贵的操作。

更有效的方法是按排序顺序存储密钥,然后如果密钥仍然可用,则 test

def min_key_order(adict:dict):
    for key in sorted(adict):
        if key in adict:
            yield (key, adict[key])

但是,如果您添加更多密钥,则无法检测到。