Python: рекурсивный генератор пропускает значения - PullRequest
0 голосов
/ 14 июля 2020

Я пытался создать функцию рекурсивного генератора в python, которая выравнивает вложенные списки . Это сделано для понимания. Вот код

def flat(list_x):
    try:
        for element in list_x:
            yield flat(element).next()
    except TypeError:
        yield list_x 

Итак, я получаю только сглаженный список первых элементов вложенных списков.

l=[[1,2],[3,4]]
a=flat(l)
list(a)
[1,3]

EDIT: Из того, что я ' Я проверил, что на самом деле происходит внутри. С тестовым списком l=[[1,2],[3,4], в котором есть подсписки [1,2] и [3,4]. Первый l oop проходит через каждый элемент основного списка, затем рекурсивный вызов генератора преобразует его go в другой для l oop, и в этот момент для первого подсписка он должен делать оба :

for 1 in [1,2]:
    yield flat(1).next()

, после чего возникнет ошибка TypeError, и будет выдано значение 1

и

for 2 in [1,2]:
    yield flat(2).next()

, в этот момент должно возникнуть другое исключение TypeError и будет выдано значение 2 но он этого не делает, отсюда и название. Я тщательно тестировал это поведение, списки можно было бы сделать длиннее или вложить глубже, но всегда будет выдан только первый элемент вложенного списка. Я как бы надеялся получить ответ за кулисами, почему он это делает, а функции, написанные точно таким же образом, этого не делают.

Итак, я хочу понять, почему он пропускает другие элементы for l oop. Я могу найти решение с функциями, выполняющими в основном то же самое. Вот код:

def flat_f(list_x, result):
    try:
        for element in list_x:
            result.append(flat_f(element,result))
    except TypeError:
            return list_x
#removing None values generated by recursive function calls(probably there is a better way of doing this) 
    for index, number in enumerate(result):
        if item==None: del result[index]

Так что я не уверен, почему это не работает, уже несколько дней бью головой об этом, если кто-нибудь может объяснить, почему я был бы очень благодарен *. 1031 *

1 Ответ

3 голосов
/ 14 июля 2020

yield flat(element).next() дает только первое значение, а затем вы отбрасываете остальную часть вложенного списка и переходите к следующему. Используйте yield from.

def flat(list_x):
    for element in list_x:
        try:
            yield from flat(element)
        except TypeError:
            yield element

Если вам нужно поддерживать Python 2, замените yield from на al oop.

def flat(list_x):
    for element in list_x:
        try:
            i = iter(element)
        except TypeError:
            yield element
        else:
            for x in i:
                yield x
...