Первая проблема заключается в том, что с if isinstance(a[i],type(dict))
вы проверяете, является ли элемент экземпляром type(dict)
, то есть type
, а не dict
, но это не решает все проблемы.
>>> type(dict)
<type 'type'>
>>> dict
<type 'dict'>
Пока вы запрашиваете решение с использованием генераторов, я не думаю, что это действительно имеет смысл, так как вы хотите вернуть словарь, а не просто повторяемый. Таким образом, вы можете использовать генератор только для внутренней функции (как и вы), что делает код излишне сложным.
Вместо этого я бы предложил использовать что-то вроде этого, которое пропускает все ваши assert
s:
def flatten(d):
res = {}
for key, val in d.items():
if isinstance(val, dict):
if not val:
res[key] = ""
for k2, v2 in flatten(val).items():
res["%s/%s" % (key, k2)] = v2
else:
res[key] = val
return res
Если вы действительно хотите сохранить этот стиль внутреннего генератора, вы можете использовать это:
def flatten(d):
return dict(_flatten_gen(d))
def _flatten_gen(d):
for key, val in d.items():
if isinstance(val, dict):
if not val:
yield (key, "")
yield from (("%s/%s" % (key, k2), v2) for k2, v2 in flatten(val).items())
else:
yield (key, val)
Обратите внимание, что это дает кортежи, которые могут быть переданы непосредственноконструктор dict
вместо объединения, а затем разделения ключей и значений на :
. (На самом деле, таким образом, может иметь смысл иметь генератор, так как вы можете просто вызвать _flatten_gen(d)
вместо flatten(d).items()
, если вы просто хотите перебрать все сплющенные элементы и не нуждаетесь в самом словаре.)