Сделать список пустым после возврата в функцию - PullRequest
0 голосов
/ 24 ноября 2018

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

Это моя текущая попытка:

 result = []

def flatten(nested_list):
    for i in nested_list:
        if type(i) != list:
            result.append(i)
        else:
            flatten(i)
    return result

Проблема в том,как только я хочу снова запустить эту функцию, она запоминает последний результат, что означает, что она добавляет все в конце.Но я хочу сделать новый результат, содержащий простой список текущих вложенных.Как удалить последний результат при повторном вызове функции?

Спасибо.

Ответы [ 3 ]

0 голосов
/ 25 ноября 2018

Проблема в том, что вы всегда используете глобальную переменную.Использование изменяемой глобальной области видимости обычно является анти-паттерном.Сохранение вашего кода по существу одинаковым.Простым подходом является использование аккумулятора и передача его в качестве аргумента рекурсивным вызовам:

In [4]: def flatten(nested_list, result=None):
   ...:     if result is None:
   ...:         result = []
   ...:     for i in nested_list:
   ...:         if type(i) != list:
   ...:             result.append(i)
   ...:         else:
   ...:             flatten(i, result)
   ...:     return result
   ...:
   ...:

In [5]: x = [[1,[2], [3,4],5]]

In [6]: flatten(x)
Out[6]: [1, 2, 3, 4, 5]

In [7]: x
Out[7]: [[1, [2], [3, 4], 5]]

In [8]: flatten(x)
Out[8]: [1, 2, 3, 4, 5]

In [9]: x
Out[9]: [[1, [2], [3, 4], 5]]

Часто, однако, вы не хотите выставлять result в качестве параметра, ожидающего стрельбысебя в ногу.Таким образом, вы можете определить «частную» вспомогательную функцию:

In [15]: def _flatten(nested_list, result):
    ...:     for i in nested_list:
    ...:         if type(i) != list:
    ...:             result.append(i)
    ...:         else:
    ...:             _flatten(i, result)
    ...:     return result
    ...:
    ...: def flatten(nested_list):
    ...:     return _flatten(nested_list, [])
    ...:
    ...:

In [16]: x = [[1,[2], [3,4],5]]

In [17]: flatten(x)
Out[17]: [1, 2, 3, 4, 5]

In [18]: x
Out[18]: [[1, [2], [3, 4], 5]]

In [19]: flatten(x)
Out[19]: [1, 2, 3, 4, 5]

Или вы можете определить свой помощник внутри своей основной функции и сжимать переменную результата в замыкании:

In [26]: def flatten(nested_list):
    ...:     result = []
    ...:     def _flatten(nested_list):
    ...:         for i in nested_list:
    ...:             if type(i) != list:
    ...:                 result.append(i)
    ...:             else:
    ...:                 _flatten(i)
    ...:
    ...:     _flatten(nested_list)
    ...:     return result
    ...:
    ...:

In [27]: flatten(x)
Out[27]: [1, 2, 3, 4, 5]

In [28]: x
Out[28]: [[1, [2], [3, 4], 5]]

In [29]: flatten(x)
Out[29]: [1, 2, 3, 4, 5]
0 голосов
/ 25 ноября 2018

Вам не нужны глобальная переменная, дополнительный аргумент, приватная вспомогательная функция или закрытие - просто знайте, когда использовать append(), а когда использовать extend():

def flatten(nested_list):
    result = []

    for i in nested_list:
        if isinstance(i, list):
            result.extend(flatten(i))
        else:
            result.append(i)

    return result

ПРИМЕР

>>> x = [[1, [2], [3, 4], 5]]
>>> flatten(x)
[1, 2, 3, 4, 5]
>>> x
[[1, [2], [3, 4], 5]]
>>> 

Также if type(i) != list:, вероятно, не является проверкой выбора типа в наши дни - isinstance() будет работать и с подклассами.

0 голосов
/ 24 ноября 2018

Причина, по которой вы столкнулись с этой проблемой, заключается в том, что result находится в неправильной области действия .Вам нужно поместить объявление result внутри функции, чтобы, когда функция заканчивается, она выходит из области видимости и больше не существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...