我目前正在尝试更加熟悉Python中的迭代器,并且遇到了一些奇怪的行为。本质上,生成器理解会导致错误的行为,而列表理解会导致正确的行为。
让我先解释一下我想做的事情,然后再说我得到的行为。
想象一下,有一个可迭代的字典,例如
d = {'a': [1, 2, 3], 'b': [4, 5]}
我想要的是列出所有迭代器可能组合的字典。对于第一个示例,这将是
l = [
{'a': 1, 'b': 4},
{'a': 1, 'b': 5},
{'a': 2, 'b': 4},
{'a': 2, 'b': 5},
{'a': 3, 'b': 4},
{'a': 3, 'b': 5},
]
为此,我创建了这个生成器:
def dict_value_iterator(d):
for k, v in d.items():
yield ((k, vi) for vi in v)
想法是运行以下代码以获得所需的结果
def get_all_dicts(d):
return map(dict, *itertools.product(dict_value_iterator(d)))
现在,为了奇怪的行为。
为了测试dict_value_iterator
生成器确实完成了我希望的功能,我运行了以下代码:
for i in dict_value_iterator(d):
print(list(i))
这确实符合我的期望,即打印出以下内容:
[('a', 1), ('a', 2), ('a', 3)]
[('b', 4), ('b', 5)]
但是,当我运行以下代码时
def test_unpacking(*args):
for a in args:
print(list(a))
test_unpacking(*dict_value_iterator(d))
我得到了输出
[('b', 1), ('b', 2), ('b', 3)]
[('b', 4), ('b', 5)]
这对我来说几乎没有意义,为什么迭代器解包会改变任何东西。
最后的提示。
我发现它的方法是在d上运行get_all_dicts
函数,结果如下:
[{'b': 4}, {'b': 5}, {'b': 4}, {'b': 5}, {'b': 4}, {'b': 5}]
但是,当我如下修改dict_value_iterator
def dict_value_iterator(d):
for k, v in d.items():
yield ((k, vi) for vi in v)
我得到这个输出
[{'a': 1, 'b': 4},
{'a': 1, 'b': 5},
{'a': 2, 'b': 4},
{'a': 2, 'b': 5},
{'a': 3, 'b': 4},
{'a': 3, 'b': 5}]
这就是我想要的。
答案 0 :(得分:2)
这是简化版:
clipToBounds
仅存在一个名为generators = []
for i in [1, 2]:
generators.append((i for _ in [1]))
print(list(generators[0])) # [2]
的变量,并且i
循环反复对其进行设置。生成器表达式创建的所有生成器都引用相同的for
,直到退出循环后才读取它。
解决此问题的一种方法是通过使用函数创建另一个作用域(例如,像在ES5中那样):
i