Как сбросить переменную, назначенную функции в Python 2.73?
Так что в основном парень помог мне улучшить мой код. Проблема в том, что он по-прежнему разочаровывает и не работает. То, что я хочу сделать, это сбросить lenRecur.number, чтобы я мог снова использовать функцию, используя другие строки и получая правильные ответы (не слишком большие ответы)
Я думаю, проблема с hasattr. Но я не могу удалить его, потому что если я это сделаю, мой калькулятор длины строки не будет работать.
В любом случае, даже если я добавлю lenRecur.number = 0 после функции, она все равно не будет работать.
Это как невозможно, потому что когда функция нажимает "возврат", это делается, точка. Если я сброслю его до "возврата", он вернет 0, неправильный ответ, так что да, у меня здесь большие проблемы.
def lenRecur(aStr):
if not hasattr(lenRecur, 'number'):
lenRecur.number = 0
'''
aStr: a string
returns: int, the length of aStr
'''
if aStr == '':
return lenRecur.number
else:
lenRecur.number += 1
return lenRecur(aStr[:-1])
PS Цель моей программы (?) / Script(?) - измерить длину входной строки без использования метода input(). Как пытаться воссоздать метод length(), используя более примитивные средства.
Сценарий должен иметь много разных входных данных, поэтому он должен быть сброшен.
3 ответа
Если вам нужна рекурсивная функция длины-длины, это просто:
def len_recur(a_str):
if not a_str:
return 0
else:
return 1 + len_recur(a_str[1:])
Конечно, это не хвостовая рекурсия, но в любом случае Python не оптимизирует хвостовую рекурсию, так что это не имеет значения.
И если вы хотите, чтобы он был хвостовым рекурсивным, просто ради этого - или потому что вы прочитали трюк Пола Батлера для Tail Recursion в Python и хотите попробовать его - вы все равно не хотите делать это, храня аккумулятор в качестве атрибута функции. Просто используйте обычный прием определения локальной функции (или, если хотите, изменяемый параметр по умолчанию):
def len_tail_recur(a_str):
def tail(a_str, acc):
if not a_str:
return acc
else:
return tail(a_str[1:], acc+1)
return tail(a_str, 0)
Если вы хотите преобразовать это в реальную хвостовую рекурсивную функцию, чтобы она не бомбила списки из 1001 элемента и не понимала ссылку Пола Батлера выше, см. Мой ответ на Получение длины списка в Python с использованием рекурсии, которая решает именно эту проблему. (Другой ответ на этот вопрос также показывает, как решить проблему с помощью рекурсивных вызовов журнала N вместо N, что является другим способом решения проблемы, если у вас нет list
с.)
При этом, несмотря на то, что ваша реализация - неправильный способ сделать это, она на самом деле работает просто отлично. (До сих пор я выполнял PEP8, если ваш код больше походил на идиоматический Python; с этого момента я просто собираюсь копировать-вставлять как есть, но ваш реальный код должен выглядеть так, как указано выше.)
def lenRecur(aStr):
if not hasattr(lenRecur, 'number'):
lenRecur.number = 0
'''
aStr: a string
returns: int, the length of aStr
'''
if aStr == '':
return lenRecur.number
else:
lenRecur.number += 1
return lenRecur(aStr[:-1])
print lenRecur('abc')
lenRecur.number = 0
print lenRecur('abcd')
Это печатает 3
, затем 4
, Конечно, вы должны установить lenRecur.number
извне функции, потому что внутри функции вам все еще нужно значение. Но вы можете решить это с помощью такой же оболочки:
def lenRecur(aStr):
lenRecur.number = 0
'''
aStr: a string
returns: int, the length of aStr
'''
def recur(aStr):
if aStr == '':
return lenRecur.number
else:
lenRecur.number += 1
return recur(aStr[:-1])
return recur(aStr)
Вам не нужно использовать переменную состояния внутри функции. Если вы хотите сделать калькулятор рекурсивной длины, просто сделайте
def lenRecur (aStr):
if (aStr == ""):
return 0
else
return lenRecur (aStr [:-1]) + 1
Также обратите внимание, что в этом стиле нет проверки ошибок и т. Д., Но в целях изучения рекурсии он работает нормально.
Если вы пытаетесь понять рекурсию, реализуя функцию длины с помощью рекурсии, вы можете использовать что-то вроде этого:
#!python
def lenRecur(something, curlen=0):
if something:
return lenRecur(something[1:], curlen+1)
else:
return curlen
... Я не буду утверждать, что это особенно хороший код. Но он должен работать с любой последовательностью (строка, список, кортеж) ... с любой, для которой будет работать операция среза [1:], если только она не превышает максимальный предел рекурсии в вашем работающем экземпляре Python.
В вашем примере вы пытаетесь реализовать аналогичную концепцию, используя hasattr для "monkey patch" объекта вашей функции с атрибутом "number". В моем примере я использую параметр по умолчанию как способ передачи переменной в рекурсивные вызовы.
Таким образом, при первоначальном вызове curlen равен нулю (вызов этого с помощью "необязательного" дополнительного аргумента даст поддельные результаты). После этого вызова функция вызывает себя со срезом исходной последовательности (строки), которая отсекает голову (сокращая ее на одну единицу) и увеличивая необязательный аргумент (curlen). В конце строка / последовательность имеет нулевую длину, ноль возвращается вверх через каждый из предыдущих (рекурсивных) вызовов.
Это слабый способ сделать это, и это может стать отправной точкой для обсуждения по устранению хвостовой рекурсии (Google для него). Но это будет работать без необходимости исправления вашей функции / объекта.