С такого родом рекурсивных проблем, вот как вы должны думать об этом:
Там должен быть «основа случай», который отвечает на вопрос тривиальным.
Должна быть часть, которая делает что-то, что приближает вас к решению.
В этом случае «базовый регистр» будет пустым. Если список пуст, верните True
.
Часть, которая приближает вас к решению: сократите список. Как только список будет укорочен вплоть до нулевого (пустого) списка, вы достигли базового варианта.
В псевдокоде:
define function all_positive(lst)
# basis case
if lst is zero-length:
return True
if the first item in the list is not positive:
return False
# the actual recursive call
return all_positive(lst[with_first_value_removed]
Попытка преобразовать выше псевдокод в код Python и получить его работу. Когда вы будете готовы заглянуть в мой ответ, это ниже.
def all_positive(lst):
"""
Recursive function to find out if all members of lst are positive.
Because it is recursive, it must only be used with short lists.
"""
# basis case
if len(lst) == 0:
return True
if lst[0] <= 0:
return False
# recursive call
return all_positive(lst[1:])
Существует несколько способов написать это. Один из способов - использовать lst.pop()
, чтобы удалить один элемент из списка. Вы могли бы объединить это с заявлением if
, и это было бы изящно. Тогда список уже будет сокращен, и вы можете просто сделать рекурсивный вызов со списком.
if lst.pop() <= 0:
return False
return all_positive(lst)
Есть одна проблема: это уничтожает список! Если вызывающий абонент не знает, что он уничтожает список, а вызывающий делает копию списка, это разрушительно. Это просто опасно. Безопаснее делать это так, как я написал выше, где вы используете «сортировку списка», чтобы сделать копию списка, который оставляет первый элемент.
Обычно на языке, таком как Python, мы хотим более безопасную программу, поэтому мы делаем копии вещей, а не разрушаем их («мутируем» их, как мы говорим).
Вот еще одна версия all_positive()
, которая делает единственную копию списка, а затем уничтожает эту копию при ее работе. Он опирается на вспомогательную функцию; помощник разрушительный. Мы не ожидаем, что пользователь вызовет вспомогательную функцию напрямую, так что у нее есть имя, которое начинается с подчеркивания.
def _all_positive_helper(lst):
"""
Recursive function that returns True if all values in a list are positive.
Don't call this directly as it destroys its argument; call all_positive() instead.
"""
if len(lst) == 0:
return True
if lst.pop() <= 0:
return False
return _all_positive_helper(lst)
def all_positive(lst):
"""
Return True if all members of lst are positive; False otherwise.
"""
# use "list slicing" to make a copy of the list
lst_copy = lst[:]
# the copy will be destroyed by the helper but we don't care!
return _all_positive_helper(lst_copy)
В Python фактически можно использовать аргумент по умолчанию для реализации выше всего в одной функции.
def all_positive(lst, _lst_copy=None):
"""
Return True if all members of lst are positive; False otherwise.
"""
if _lst_copy is None:
return all_positive(lst, lst[:])
if len(_lst_copy) == 0:
return True
if _lst_copy.pop() <= 0:
return False
return all_positive(lst, _lst_copy)
Рекурсия на самом деле не поможет вам в этом. Лучшее использование для рекурсии было бы, например, посещением каждого узла в двоичном дереве.
Отступ 'if (number <= 0):' представляется неправильным, но я предполагаю, что он является частью предыдущего определения функции. –