Python ';非类型';递归解析dict时不可iterable吗?

Python ';非类型';递归解析dict时不可iterable吗?,python,dictionary,recursion,data-structures,Python,Dictionary,Recursion,Data Structures,使用此功能: def extract_flat_branch(nested_dict, c = []): for i in ['left', 'op', 'right', 'func', 'value', 'args', 'ctx', 'body', 'comparators', 'ops', 'test', 'orelse', 'targets', 'slice']: if i in nested_dict: if

使用此功能:

def extract_flat_branch(nested_dict, c = []):
    for i in ['left', 'op', 'right', 'func', 'value', 'args', 
              'ctx', 'body', 'comparators', 'ops', 'test', 'orelse', 'targets', 'slice']:
        if i in nested_dict:
            if isinstance(nested_dict[i], list):
                for b in nested_dict[i]:
                    yield from extract_flat_branch(b, c+[nested_dict['_type']]) 
            else:
                yield from extract_flat_branch(nested_dict[i], c+[nested_dict['_type']]) 
    lis = [c+[nested_dict['_type'], i] for i in filter(None, [nested_dict.get(j) for j in ['n', 'id']])]
    yield from lis if lis else [c+[nested_dict['_type']]] if len(nested_dict) == 1 else []
我正在遍历并提取这棵树的分支(表示为this dictionary()),它是一个字符串列表,其中树的所有分支都是一个平面列表的元素。然而,出于某种原因,当我这样做时:

在:

而不是获得类似的输出:

[[node_1, node_2, .., node_n],[node_1, node_2, .., node_n],...,[node_1, node_2, .., node_n]]
我得到:

TypeError: argument of type 'NoneType' is not iterable
基于此,我认为问题在于我正在使用的
.get(j)
。但是,如果我在['n',id']]中嵌套了[code>dict.get(j)或{}for j我仍然会得到相同的
TypeError
。你知道如何解决这个问题并获得树的分支的平面列表吗

这是完整跟踪

TypeError                                 Traceback (most recent call last)
<ipython-input-4-51bfd7bbf4e4> in <module>
      1 for i,j in enumerate(a_lis):
      2     print(i)
----> 3     print(list(extract_flat_branch(j)))

~/dir/util.py in extract_flat_branch(nested_dict, c)
     38             if isinstance(nested_dict[i], list):
     39                 for b in nested_dict[i]:
---> 40                     yield from extract_flat_branch(b, c+[nested_dict['_type']])
     41             else:
     42                 yield from extract_flat_branch(nested_dict[i], c+[nested_dict['_type']])

~/dir/util.py in extract_flat_branch(nested_dict, c)
     38             if isinstance(nested_dict[i], list):
     39                 for b in nested_dict[i]:
---> 40                     yield from extract_flat_branch(b, c+[nested_dict['_type']])
     41             else:
     42                 yield from extract_flat_branch(nested_dict[i], c+[nested_dict['_type']])

~/dir/util.py in extract_flat_branch(nested_dict, c)
     40                     yield from extract_flat_branch(b, c+[nested_dict['_type']])
     41             else:
---> 42                 yield from extract_flat_branch(nested_dict[i], c+[nested_dict['_type']])
     43     lis = [c+[nested_dict['_type'], i] for i in filter(None, [nested_dict.get(j) for j in ['n', 'id']])]
     44     yield from lis if lis else [c+[nested_dict['_type']]] if len(nested_dict) == 1 else []

~/dir/util.py in extract_flat_branch(nested_dict, c)
     38             if isinstance(nested_dict[i], list):
     39                 for b in nested_dict[i]:
---> 40                     yield from extract_flat_branch(b, c+[nested_dict['_type']])
     41             else:
     42                 yield from extract_flat_branch(nested_dict[i], c+[nested_dict['_type']])

~/dir/util.py in extract_flat_branch(nested_dict, c)
     40                     yield from extract_flat_branch(b, c+[nested_dict['_type']])
     41             else:
---> 42                 yield from extract_flat_branch(nested_dict[i], c+[nested_dict['_type']])
     43     lis = [c+[nested_dict['_type'], i] for i in filter(None, [nested_dict.get(j) for j in ['n', 'id']])]
     44     yield from lis if lis else [c+[nested_dict['_type']]] if len(nested_dict) == 1 else []

~/dir/util.py in extract_flat_branch(nested_dict, c)
     35     for i in ['left', 'op', 'right', 'func', 'value', 'args', 
     36               'ctx', 'body', 'comparators', 'ops', 'test', 'orelse', 'targets', 'slice']:
---> 37         if i in nested_dict:
     38             if isinstance(nested_dict[i], list):
     39                 for b in nested_dict[i]:

TypeError: argument of type 'NoneType' is not iterable
TypeError回溯(最近一次调用)
在里面
1表示枚举中的i,j(a_lis):
2印刷品(一)
---->3打印(列表(摘录平面分支(j)))
提取平面分支中的~/dir/util.py(嵌套目录,c)
38如果存在(嵌套目录[i],列表):
39对于嵌套目录[i]中的b:
--->40抽提扁平分支的产量(b,c+[嵌套目录[''类型]]
41其他:
42提取扁平分支的产量(嵌套式目录[i],c+[嵌套式目录[''类型]]
提取平面分支中的~/dir/util.py(嵌套目录,c)
38如果存在(嵌套目录[i],列表):
39对于嵌套目录[i]中的b:
--->40抽提扁平分支的产量(b,c+[嵌套目录[''类型]]
41其他:
42提取扁平分支的产量(嵌套式目录[i],c+[嵌套式目录[''类型]]
提取平面分支中的~/dir/util.py(嵌套目录,c)
40抽提扁平分支的产量(b,c+[嵌套目录[''类型]]
41其他:
--->42提取扁平分支的产量(嵌套式目录[i],c+[嵌套式目录[''类型]]
43 lis=[c+[nested_dict[''u type'],i]表示过滤器中的i(无[nested_dict.get(j)表示过滤器中的j['n','id'])]
44如果lis else[c+[nested_-dict[''U-type']]如果len(nested_-dict)=1 else[]
提取平面分支中的~/dir/util.py(嵌套目录,c)
38如果存在(嵌套目录[i],列表):
39对于嵌套目录[i]中的b:
--->40抽提扁平分支的产量(b,c+[嵌套目录[''类型]]
41其他:
42提取扁平分支的产量(嵌套式目录[i],c+[嵌套式目录[''类型]]
提取平面分支中的~/dir/util.py(嵌套目录,c)
40抽提扁平分支的产量(b,c+[嵌套目录[''类型]]
41其他:
--->42提取扁平分支的产量(嵌套式目录[i],c+[嵌套式目录[''类型]]
43 lis=[c+[nested_dict[''u type'],i]表示过滤器中的i(无[nested_dict.get(j)表示过滤器中的j['n','id'])]
44如果lis else[c+[nested_-dict[''U-type']]如果len(nested_-dict)=1 else[]
提取平面分支中的~/dir/util.py(嵌套目录,c)
35对于['left','op','right','func','value','args'中的i,
36“ctx”、“主体”、“比较器”、“ops”、“测试”、“orelse”、“目标”、“切片”]:
--->37如果我在嵌套目录中:
38如果存在(嵌套目录[i],列表):
39对于嵌套目录[i]中的b:
TypeError:类型为“NoneType”的参数不可编辑

引发
NoneType
错误,因为在您的数据中有一个特定的
“value”
键,该键被散列到相应的
None
<代码>“值”是函数签名正下方的键列表中的目标键,当前逻辑尝试检查函数输入
嵌套\u dict
中是否存在任何此类键。对于具有
None
值的目标键,不清楚您想要的输出是什么,但一个简单的解决方法是检查并忽略这种情况:

def extract_flat_branch(nested_dict, c = []):
   for i in ['left', 'op', 'right', 'func', 'value', 'args', 'ctx', 'body', 'comparators', 'ops', 'test', 'orelse', 'targets', 'slice', 'n', 'id']:
      if i in nested_dict:
        if isinstance(nested_dict[i], list):
            for b in nested_dict[i]:
                yield from extract_flat_branch(b, c+[nested_dict['_type']]) 
        elif isinstance(nested_dict[i], dict): #simple check here
            yield from extract_flat_branch(nested_dict[i], c+[nested_dict['_type']]) 
        else:
            yield c+[nested_dict[i]]


print(list(extract_flat_branch(data)))
输出:

[['FunctionDef', 'Assign', 'Call', 'Name', 'Load'], ['FunctionDef', 'Assign', 'Call', 'Name', 'list'], ['FunctionDef', 'Assign', 'Call', 'Name', 'Load'], ['FunctionDef', 'Assign', 'Call', 'Name', 'items'], ['FunctionDef', 'Assign', 'Name', 'Store'], ['FunctionDef', 'Assign', 'Name', 'items'], ['FunctionDef', 'Assign', 'Call', 'Name', 'Load'], ['FunctionDef', 'Assign', 'Call', 'Name', 'next_power_of_two'], ['FunctionDef', 'Assign', 'Call', 'Call', 'Name', 'Load'], ['FunctionDef', 'Assign', 'Call', 'Call', 'Name', 'int'], ['FunctionDef', 'Assign', 'Call', 'Call', 'BinOp', 'Num', 1.2], ['FunctionDef', 'Assign', 'Call', 'Call', 'BinOp', 'Mult'], ['FunctionDef', 'Assign', 'Call', 'Call', 'BinOp', 'Call', 'Name', 'Load'], ['FunctionDef', 'Assign', 'Call', 'Call', 'BinOp', 'Call', 'Name', 'len'], ['FunctionDef', 'Assign', 'Call', 'Call', 'BinOp', 'Call', 'Name', 'Load'], ['FunctionDef', 'Assign', 'Call', 'Call', 'BinOp', 'Call', 'Name', 'items'], ['FunctionDef', 'Assign', 'Name', 'Store'], ['FunctionDef', 'Assign', 'Name', 'size'], ['FunctionDef', 'Assign', 'BinOp', 'List', 'Load'], ['FunctionDef', 'Assign', 'BinOp', 'Mult'], ['FunctionDef', 'Assign', 'BinOp', 'Name', 'Load'], ['FunctionDef', 'Assign', 'BinOp', 'Name', 'size'], ['FunctionDef', 'Assign', 'Name', 'Store'], ['FunctionDef', 'Assign', 'Name', 'table'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Call', 'Name', 'Load'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Call', 'Name', 'hash_function'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Call', 'Name', 'Load'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Call', 'Name', 'i'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Mod'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Name', 'Load'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Name', 'size'], ['FunctionDef', 'For', 'Assign', 'Name', 'Store'], ['FunctionDef', 'For', 'Assign', 'Name', 'h'], ['FunctionDef', 'For', 'Assign', 'Name', 'Store'], ['FunctionDef', 'For', 'Assign', 'Name', 's'], ['FunctionDef', 'For', 'While', 'AugAssign', 'Add'], ['FunctionDef', 'For', 'While', 'AugAssign', 'Num', 1], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'BinOp', 'Name', 'Load'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'BinOp', 'Name', 'h'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'BinOp', 'Add'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'BinOp', 'Name', 'Load'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'BinOp', 'Name', 's'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'Mod'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'Name', 'Load'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'Name', 'size'], ['FunctionDef', 'For', 'While', 'Assign', 'Name', 'Store'], ['FunctionDef', 'For', 'While', 'Assign', 'Name', 'h'], ['FunctionDef', 'For', 'While', 'Compare', 'Subscript', 'Name', 'Load'], ['FunctionDef', 'For', 'While', 'Compare', 'Subscript', 'Name', 'table'], ['FunctionDef', 'For', 'While', 'Compare', 'Subscript', 'Load'], ['FunctionDef', 'For', 'While', 'Compare', 'Subscript', 'Index', 'Name', 'Load'], ['FunctionDef', 'For', 'While', 'Compare', 'Subscript', 'Index', 'Name', 'h'], ['FunctionDef', 'For', 'While', 'Compare', None], ['FunctionDef', 'For', 'While', 'Compare', 'IsNot'], ['FunctionDef', 'For', 'Assign', 'Name', 'Load'], ['FunctionDef', 'For', 'Assign', 'Name', 'i'], ['FunctionDef', 'For', 'Assign', 'Subscript', 'Name', 'Load'], ['FunctionDef', 'For', 'Assign', 'Subscript', 'Name', 'table'], ['FunctionDef', 'For', 'Assign', 'Subscript', 'Store'], ['FunctionDef', 'For', 'Assign', 'Subscript', 'Index', 'Name', 'Load'], ['FunctionDef', 'For', 'Assign', 'Subscript', 'Index', 'Name', 'h'], ['FunctionDef', 'Return', 'Name', 'Load'], ['FunctionDef', 'Return', 'Name', 'table']]
[['FunctionDef'], ['args', 'arguments'], ['args', 'args', 'arg'], ['args', 'args', None], ['args', 'args', 'self'], ['body', 'Expr'], ['body', 'value', 'Str'], ['body', 'value', 'Like items(), but with all lowercase keys.'], ['body', 'Return'], ['body', 'value', 'GeneratorExp']]

更新的解决方案:

def extract_flat_branch(nested_dict, c = []):
  targets = {'left', 'op', 'right', 'func', 'value', 'args', 'ctx', 'body', 'comparators', 'ops', 'test', 'orelse', 'targets', 'slice', 'n', 'id', 'slice', 'annotation', 'arg', 'elts', 's', '_type'}
  for a, b in nested_dict.items():
     if a in targets:
        if isinstance(b, dict):
           yield from extract_flat_branch(b, c+[a])
        elif isinstance(b, list):
           for i in b:
              yield from extract_flat_branch(i, c+[a])
        else:
            yield c+[b]

print(list(extract_flat_branch(data)))
输出:

[['FunctionDef', 'Assign', 'Call', 'Name', 'Load'], ['FunctionDef', 'Assign', 'Call', 'Name', 'list'], ['FunctionDef', 'Assign', 'Call', 'Name', 'Load'], ['FunctionDef', 'Assign', 'Call', 'Name', 'items'], ['FunctionDef', 'Assign', 'Name', 'Store'], ['FunctionDef', 'Assign', 'Name', 'items'], ['FunctionDef', 'Assign', 'Call', 'Name', 'Load'], ['FunctionDef', 'Assign', 'Call', 'Name', 'next_power_of_two'], ['FunctionDef', 'Assign', 'Call', 'Call', 'Name', 'Load'], ['FunctionDef', 'Assign', 'Call', 'Call', 'Name', 'int'], ['FunctionDef', 'Assign', 'Call', 'Call', 'BinOp', 'Num', 1.2], ['FunctionDef', 'Assign', 'Call', 'Call', 'BinOp', 'Mult'], ['FunctionDef', 'Assign', 'Call', 'Call', 'BinOp', 'Call', 'Name', 'Load'], ['FunctionDef', 'Assign', 'Call', 'Call', 'BinOp', 'Call', 'Name', 'len'], ['FunctionDef', 'Assign', 'Call', 'Call', 'BinOp', 'Call', 'Name', 'Load'], ['FunctionDef', 'Assign', 'Call', 'Call', 'BinOp', 'Call', 'Name', 'items'], ['FunctionDef', 'Assign', 'Name', 'Store'], ['FunctionDef', 'Assign', 'Name', 'size'], ['FunctionDef', 'Assign', 'BinOp', 'List', 'Load'], ['FunctionDef', 'Assign', 'BinOp', 'Mult'], ['FunctionDef', 'Assign', 'BinOp', 'Name', 'Load'], ['FunctionDef', 'Assign', 'BinOp', 'Name', 'size'], ['FunctionDef', 'Assign', 'Name', 'Store'], ['FunctionDef', 'Assign', 'Name', 'table'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Call', 'Name', 'Load'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Call', 'Name', 'hash_function'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Call', 'Name', 'Load'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Call', 'Name', 'i'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Mod'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Name', 'Load'], ['FunctionDef', 'For', 'Assign', 'BinOp', 'Name', 'size'], ['FunctionDef', 'For', 'Assign', 'Name', 'Store'], ['FunctionDef', 'For', 'Assign', 'Name', 'h'], ['FunctionDef', 'For', 'Assign', 'Name', 'Store'], ['FunctionDef', 'For', 'Assign', 'Name', 's'], ['FunctionDef', 'For', 'While', 'AugAssign', 'Add'], ['FunctionDef', 'For', 'While', 'AugAssign', 'Num', 1], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'BinOp', 'Name', 'Load'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'BinOp', 'Name', 'h'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'BinOp', 'Add'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'BinOp', 'Name', 'Load'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'BinOp', 'Name', 's'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'Mod'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'Name', 'Load'], ['FunctionDef', 'For', 'While', 'Assign', 'BinOp', 'Name', 'size'], ['FunctionDef', 'For', 'While', 'Assign', 'Name', 'Store'], ['FunctionDef', 'For', 'While', 'Assign', 'Name', 'h'], ['FunctionDef', 'For', 'While', 'Compare', 'Subscript', 'Name', 'Load'], ['FunctionDef', 'For', 'While', 'Compare', 'Subscript', 'Name', 'table'], ['FunctionDef', 'For', 'While', 'Compare', 'Subscript', 'Load'], ['FunctionDef', 'For', 'While', 'Compare', 'Subscript', 'Index', 'Name', 'Load'], ['FunctionDef', 'For', 'While', 'Compare', 'Subscript', 'Index', 'Name', 'h'], ['FunctionDef', 'For', 'While', 'Compare', None], ['FunctionDef', 'For', 'While', 'Compare', 'IsNot'], ['FunctionDef', 'For', 'Assign', 'Name', 'Load'], ['FunctionDef', 'For', 'Assign', 'Name', 'i'], ['FunctionDef', 'For', 'Assign', 'Subscript', 'Name', 'Load'], ['FunctionDef', 'For', 'Assign', 'Subscript', 'Name', 'table'], ['FunctionDef', 'For', 'Assign', 'Subscript', 'Store'], ['FunctionDef', 'For', 'Assign', 'Subscript', 'Index', 'Name', 'Load'], ['FunctionDef', 'For', 'Assign', 'Subscript', 'Index', 'Name', 'h'], ['FunctionDef', 'Return', 'Name', 'Load'], ['FunctionDef', 'Return', 'Name', 'table']]
[['FunctionDef'], ['args', 'arguments'], ['args', 'args', 'arg'], ['args', 'args', None], ['args', 'args', 'self'], ['body', 'Expr'], ['body', 'value', 'Str'], ['body', 'value', 'Like items(), but with all lowercase keys.'], ['body', 'Return'], ['body', 'value', 'GeneratorExp']]

@00,我添加了完整的跟踪,谢谢help@JDo很乐意帮忙@JDo如果您首先有一个
None
,然后是一个
bool
而不是iterable,那么您可能应该检查
nested_dict[i]
是否是iterable(但要注意字符串)。再者,考虑到这种情况更为频繁,可能您的代码逻辑(或您的输入,但可能性较小)需要更全面的检查。@JDo请参阅我最近的编辑。因为目标键似乎可以存储任何类型的值,所以我认为最好的方法就是检查
nested_dict[I]
是否是一个iterable.@JDo我不确定输出是否是您现在正在寻找的,但在本例中,我添加了一行
yield c+[nested_dict[I]]
在目标键的值不可编辑的情况下生成输出行。请看我最近的编辑。@JDo没问题,让我看看