由于不相关的原因,我以某种方式组合了一些数据结构,同时还将 Python 2.7 的默认设置替换dict为OrderedDict. 数据结构使用元组作为字典中的键。请忽略那些细节(dict类型的替换在下面没有用,但在真实代码中)。
import __builtin__
import collections
import contextlib
import itertools
def combine(config_a, config_b):
return (dict(first, **second) for first, second in itertools.product(config_a, config_b))
@contextlib.contextmanager
def dict_as_ordereddict():
dict_orig = __builtin__.dict
try:
__builtin__.dict = collections.OrderedDict
yield
finally:
__builtin__.dict = dict_orig
这最初按预期工作(dict可以将非字符串关键字参数作为特例):
print 'one level nesting'
with dict_as_ordereddict():
result = combine(
[{(0, 1): 'a', (2, 3): 'b'}],
[{(4, 5): 'c', (6, 7): 'd'}]
)
print list(result)
输出:
one level nesting
[{(0, 1): 'a', (4, 5): 'c', (2, 3): 'b', (6, 7): 'd'}]
但是,当嵌套调用combine生成器表达式时,可以看出dict引用被视为OrderedDict,缺少dict使用元组作为关键字参数的特殊行为:
print 'two level nesting'
with dict_as_ordereddict():
result = combine(combine(
[{(0, 1): 'a', (2, 3): 'b'}],
[{(4, 5): 'c', (6, 7): 'd'}]
),
[{(8, 9): 'e', (10, 11): 'f'}]
)
print list(result)
输出:
two level nesting
Traceback (most recent call last):
File "test.py", line 36, in <module>
[{(8, 9): 'e', (10, 11): 'f'}]
File "test.py", line 8, in combine
return (dict(first, **second) for first, second in itertools.product(config_a, config_b))
File "test.py", line 8, in <genexpr>
return (dict(first, **second) for first, second in itertools.product(config_a, config_b))
TypeError: __init__() keywords must be strings
此外,实现 viayield而不是生成器表达式解决了这个问题:
def combine_yield(config_a, config_b):
for first, second in itertools.product(config_a, config_b):
yield dict(first, **second)
问题:
为什么生成器表达式中的某些项目(仅第一个?)在第二个示例中需要之前被评估,或者它需要什么?
为什么在第一个示例中没有对其进行评估?我实际上期望两者都有这种行为。
为什么yield
基于 - 的版本有效?
holdtom
相关分类