Python(3.4)在dict / tree flattening上没有调用递归函数

时间:2015-04-22 20:02:42

标签: python dictionary recursion tree

我正在尝试压扁嵌套字典,同时根据另一个嵌套字典交换其键。我假设没有一个分支具有相同的密钥。 E.g:

在:

values_dict_test = {"abs": 3, "cd": 23, "sdf": "abc", "gxr":
{"rea": 21, "bdf": 95}}
mapping_dict_test = {"abs": "one", "cd": "two", "sdf": "three", "gxr":
{"rea": "four", "bdf": "five"}}

期待:

{"one": 3, "two": 23, "three": "abc", "four": 21, "five": 95}

我正在使用iteritems hack尝试使此代码与Python 2.7兼容,但我正在测试3.4。我添加了一堆print语句来跟踪执行情况;似乎递归调用从未真正发生过。

try:
    dict.iteritems
except AttributeError:
    # Python 3
    def itervalues(d):
        return iter(d.values())
    def iteritems(d):
        return iter(d.items())
else:
    # Python 2
    def itervalues(d):
        return d.itervalues()
    def iteritems(d):
        return d.iteritems()

def flatten_dict(mapping, values_dict):
    print("Function called with {} and {}".format(mapping, values_dict))
    for (key, value) in iteritems(mapping):
        print("K: {} V: {} Mapping: {}".format(key, value, mapping))
        if isinstance(value, dict):
            # Note that we have to flatten the values_dict as we flatten
            # mapping dict, hence the [key]
            print("Going to recurse")
            print("Passing {} and {}".format(value, values_dict[key]))
            flatten_dict(value, values_dict[key])
        else:
            print("Going to yield {}, {}".format(value, values_dict[key]))
            yield (value, values_dict[key])

values_dict_test = {"abs": 3, "cd": 23, "sdf": "abc", "gxr":
{"rea": 21, "bdf": 95}}
mapping_dict_test = {"abs": "one", "cd": "two", "sdf": "three", "gxr":
{"rea": "four", "bdf": "five"}}

for (x,y) in flatten_dict(mapping_dict_test, values_dict_test):
    print(x, y)

输出:

Function called with {'cd': 'two', 'sdf': 'three', 'abs': 'one', 'gxr': {'rea': 'four', 'bdf': 'five'}} and {'cd': 23, 'sdf': 'abc', 'abs': 3, 'gxr': {'rea': 21, 'bdf': 95}}
K: cd V: two Mapping: {'cd': 'two', 'sdf': 'three', 'abs': 'one', 'gxr': {'rea': 'four', 'bdf': 'five'}}
Going to yield two, 23
two 23
K: sdf V: three Mapping: {'cd': 'two', 'sdf': 'three', 'abs': 'one', 'gxr': {'rea': 'four', 'bdf': 'five'}}
Going to yield three, abc
three abc
K: abs V: one Mapping: {'cd': 'two', 'sdf': 'three', 'abs': 'one', 'gxr': {'rea': 'four', 'bdf': 'five'}}
Going to yield one, 3
one 3
K: gxr V: {'rea': 'four', 'bdf': 'five'} Mapping: {'cd': 'two', 'sdf': 'three', 'abs': 'one', 'gxr': {'rea': 'four', 'bdf': 'five'}}
Going to recurse
Passing {'rea': 'four', 'bdf': 'five'} and {'rea': 21, 'bdf': 95}

(通常,我会使用values = {key: value for (key, value) in values_dict_gen},其中values_dict_gen是该函数返回的生成器。)

编辑:赞成重新开放,(1)链接的副本使用一个可变的默认参数,已知在这些情况下反直觉行为(2)它更老,下面给出的答案显示了Python 3.3解决方案我没有看到旧的问题。

1 个答案:

答案 0 :(得分:4)

flatten_dict(value, values_dict[key])

此调用在生成器内部执行与在外部相同的操作;它创建了一个生成器对象。它不会自动运行生成器并生成其项目。如果你想以递归方式使用生成器,你必须自己迭代它:

for item in flatten_dict(value, values_dict[key]):
    yield item

或在Python 3中:

yield from flatten_dict(value, values_dict[key])