модел за оценка на параметър на функция на python

Гледах статия на уебсайта на Peter Norvig, където той се опитва да отговори на следния въпрос (това не е моят въпрос, между другото) „Мога ли да направя еквивалента на (тест? резултат: алтернатива) в Python?“

ето една от опциите, изброени от него,

def if_(test, result, alternative=None):
    "If test is true, 'do' result, else alternative. 'Do' means call if callable."
    if test:
        if callable(result): result = result()
        return result
    else:
        if callable(alternative): alternative = alternative()
        return alternative

И ето един пример за употреба.

>>> fact = lambda n: if_(n <= 1, 1, lambda: n * fact(n-1))
>>> fact(6)
720

Разбирам как работи това (мисля), но просто си играех с кода и реших да видя какво ще се случи, когато променя третия аргумент в дефиницията на „факт“ по-горе на n * fact(n-1), че е, променете го на неизвикваем израз. При стартирането му интерпретаторът влиза в безкраен цикъл. Имам доста добра представа защо това се случва, тоест функцията if_ връща обратно същия израз, който получава. Но какъв е видът на този израз? Какво точно се случва тук? Не търся подробно обяснение, а само някои насоки към модела за оценка на Python, който може да помогне за разбирането ми.

Благодаря!


person fsm    schedule 26.04.2010    source източник
comment
Вероятно няма връзка, но можете просто да използвате result if test else alternative.   -  person kennytm    schedule 26.04.2010


Отговори (1)


Причината, поради която цикълът никога не прекратява, когато промените fact на n * fact(n-1), е, че n * fact(n-1) трябва първо да оцени (като трети аргумент на if). Оценяването му води до друго извикване на fact, ad infinitum (тъй като вече няма основен случай, който да го спре).

Преди това предавахте функционален обект (lambda), който нямаше да бъде оценен до тялото на if, а резултатът му щеше да бъде проверен чрез test.

Това е известно (според мен) като нетърпелива оценка, при която аргументите на функцията се оценяват, преди да бъдат предадени на функцията. В схема за мързелива оценка аргументите няма да бъдат оценени, докато не бъдат използвани в тялото на функцията.

person danben    schedule 26.04.2010
comment
Ако n‹=1 бъде оценено правилно, рекурсията ще спре при n = 1, връщайки 1. - person Krab; 26.04.2010
comment
n <= 1 ще бъде оценено, но стойността му никога не се проверява, докато не влезе в тялото на функцията. Когато той използва рекурсивен израз вместо ламбда като трети параметър, тялото на функцията никога не се достига. - person danben; 26.04.2010
comment
Не твърдях, че изчислява n!, просто разбрах грешно отговора ви. Сега го прочетох още веднъж и съм съгласен с него. - person Krab; 26.04.2010
comment
@fsm - няма за какво. Ако намерите този отговор за полезен, ще съм благодарен, ако го маркирате като приет. - person danben; 27.04.2010