LINUX.ORG.RU

[python][recursion]не понимаю

 ,


0

0

есть задачка из sicp по вычислению квадратного корня. все вроде верно написал, но питон удивил своим поведением:

def sqrt_iter(guess, x):
    '''
    >>> sqrt_iter(1, 2)
    1.43
    '''

    if good_enought(guess, x) is False:
        sqrt_iter(improve_guess(guess, x), x)
    else:
        return guess

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

★★★★★

остальной код если надо:

def sqr(x):
    '''
    >>> sqr(4)
    16
    '''
    
    a = x * x
    return a


def average(x, y):
    '''
    >>> average(2, 3)
    2.5
    '''
    
    s = (x + y) / 2.0
    return s
    

def good_enought(guess, x):
    '''
    >>> good_enought(1.41, 2)
    False
    '''
    
    if abs(sqr(guess) - x) < 0.001:
        return True
    else:
        return False


def improve_guess(guess, x):
    '''
    >>> improve_guess(1, 2)
    1.5
    '''
    
    return average(guess, x / guess)

stave ★★★★★
() автор топика
Ответ на: комментарий от stave

>> Это определение функции, что оно должно возвращать?

> корень числа

Корень какого числа? Короче, запускабельный тест - в студию. Или ты о том, что doctest делает что-то не то?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

я с доктестом гоняю, без него тоже самое

#!/usr/bin/env python

def sqr(x):
    '''
    >>> sqr(4)
    16
    '''
    
    a = x * x
    return a
    

def abs(x):
    '''
    >>> abs(-45)
    45
    '''
    
    if x < 0:
        x = -x
    return x
    
    
def average(x, y):
    '''
    >>> average(2, 3)
    2.5
    '''
    
    s = (x + y) / 2.0
    return s
    

def good_enought(guess, x):
    '''
    >>> good_enought(1.41, 2)
    False
    '''
    
    if abs(sqr(guess) - x) < 0.001:
        return True
    else:
        return False


def improve_guess(guess, x):
    '''
    >>> improve_guess(1, 2)
    1.5
    '''
    
    return average(guess, x / guess)
    
    
def sqrt_iter(guess, x):
    '''
    >>> sqrt_iter(1, 2)
    1.43
    '''

    if good_enought(guess, x) is False:
        sqrt_iter(improve_guess(guess, x), x)
    else:
        return guess
 
    
if __name__ == "__main__":
    import doctest
    doctest.testmod()

stave ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

>Питон - это не Схема. Поставь return перед sqrt_iter

елки-палки, как просто :)
спасибо

stave ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

> Поставь return перед sqrt_iter

В питоне нормально иметь функцию, которая иногда ничего не возвращает, а иногда возвращает?

Тут сразу вспоминается статическая типизация и монада Maybe...

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>> Поставь return перед sqrt_iter

> У питона есть ключики, чтобы варнинговать такие ляпы?

Нет. Может быть, pylint умеет такое ловить.

> В питоне нормально иметь функцию, которая иногда ничего не возвращает, а иногда возвращает?

Нет. Кроме того, возвращаемый результат есть всегда, просто в случает таких ошибок это None.

tailgunner ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> У питона есть ключики, чтобы варнинговать такие ляпы?

В питоне можно столько наляпать, что воняющий анализатор был бы больше самого питона.

const86 ★★★★★
()
Ответ на: комментарий от tailgunner

> Нет. Кроме того, возвращаемый результат есть всегда, просто в случает таких ошибок это None

Чуть точнее сформулирую -- общепринятое понятие о хорошем стиле программирования в питоне допускает наличие функций, иногда возвращающих значение, а иногда None?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> общепринятое понятие о хорошем стиле программирования в питоне допускает наличие функций, иногда возвращающих значение, а иногда None?

Я не знаю насчет общепринятых, но наши - допускают. Это как возврат NULL в Си.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Я не знаю насчет общепринятых, но наши - допускают. Это как возврат NULL в Си.

Все же надо иметь возможность сказать, возвратит эта функция NULL или нет.

В плюсах есть достаточной убогий, но все же выбор -- возвращать Klass* или Klass&. В IDEA для явы есть ей поддерживаемый атирбут (точное название запамятовал) @null или @notnull.

Аналогом для динамического язык могла бы быть:

1. во время компиляции приделать функции атрибут "может возвращать None"

2. во время исполнения, даже если из функции вернулся нормальный объект, когда у него пытаются вызвать методы -- варнинговать насчет "possibly None object was not checked"

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> В IDEA для явы есть ей поддерживаемый атирбут (точное название запамятовал) @null или @notnull.

Проверяемый на этапе компиляции? Сомнительно как-то. А если на этапе выполнения, то и в Питоне это делается простым декоратором.

> во время исполнения, даже если из функции вернулся нормальный объект, когда у него пытаются вызвать методы -- варнинговать насчет "possibly None object was not checked"

Зачем?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Проверяемый на этапе компиляции? Сомнительно как-то.

Я так понял, что именно компиляции. Может они явовскую стандартную библиотеку аннотировали, там уже есть?

>> во время исполнения, даже если из функции вернулся нормальный объект, когда у него пытаются вызвать методы -- варнинговать насчет "possibly None object was not checked"

> Зачем?

Затем, что маловероятно, что ты смог предсказать, что функции вылезет не-None, а значит скорее всего упустил проверку. Нет?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

s/что функции/что из функции/
s/, там уже есть?/, или там уже есть?/

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>> Проверяемый на этапе компиляции? Сомнительно как-то.

> Я так понял, что именно компиляции. Может они явовскую стандартную библиотеку аннотировали, там уже есть?

Чтобы этот декоратор работал, нужно зааннотировать вообще всё.

> маловероятно, что ты смог предсказать, что функции вылезет не-None, а значит скорее всего упустил проверку. Нет?

Нужно просто проверять, что функция всегда дает None (или всегда не-None), это элементарно делается. Сложности с проверкой вызовов методов просто не нужны.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Нужно просто проверять, что функция всегда дает None (или всегда не-None), это элементарно делается. Сложности с проверкой вызовов методов просто не нужны.

Долго читал, но так и не понял.

www_linux_org_ru ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.