Бесконечная рекурсия в python коде для факториала с использованием метода dict.get () - PullRequest
1 голос
/ 07 апреля 2020

Я написал Python функцию для вычисления факториала числа, например, так:

def fact(n):
    return {0: 1}.get(n, n * fact(n-1))

Я был удивлен, увидев, что это приводит к бесконечной рекурсии, даже для fact(0). Затем я добавил утверждение, вот так:

def fact(n):
    assert n >= 0
    return {0: 1}.get(n, n * fact(n-1))

Но на этот раз AssertionError повышается, что означает n становится отрицательным. Я не понимаю этого. Я посмотрел это на inte rnet. Но, к сожалению, не смог найти никакого ответа. Может кто-нибудь объяснить мне, что здесь происходит?

Ответы [ 2 ]

3 голосов
/ 07 апреля 2020

В Python вызовы функций используют «нетерпеливую» оценку - значения вычисляются до вызова функции, а не для их вычисления, когда функция фактически использует их.

Таким образом, в

    {0: 1}.get(n, n * fact(n-1))

Выражение n * fact(n-1) оценивается перед , даже вызывая get(). Т.е. выражение вычисляется, даже если get () вообще не нуждается в значении. Это то, что вызывает рекурсию.

2 голосов
/ 07 апреля 2020

dict.get(item, default=None) - это просто функция, принимающая 1 или, необязательно, два аргумента. Если вы передадите n * fact(n-1) в качестве значения по умолчанию, это выражение будет оценено перед передачей. Вся конструкция

return {0: 1}.get(n, n * fact(n-1))

кажется немного искусственной. Более простой

return n * fact(n-1) if n else 1

столь же лаконичен и будет оценивать соответствующие выражения только тогда, когда фактически введена их логическая ветвь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...