Как сбросить переменную, назначенную функции в 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 для него). Но это будет работать без необходимости исправления вашей функции / объекта.

Другие вопросы по тегам