Почему не работает setrecursionlimit
from functools import lru_cache
import sys
sys.setrecursionlimit(10000)
@lru_cache(None)
def f(n):
if n == 1:
return 1
if n == 2:
return 2
if n > 2:
return n * f(n - 1) - f(n - 2)
print(f(2024) + f(2020) - f(2019))
При попытке выполнения показывается ошибка, и указано, что строка была выполнена 996 раз, хотя лимит стоит на 10000.
File "D:\PyCharm\pythonProject\practice.py", line 307, in <module>
print(f(2024) + f(2020) - f(2019))
^^^^^^^
File "D:\PyCharm\pythonProject\practice.py", line 304, in f
return n * f(n - 1) - f(n - 2)
^^^^^^^^
File "D:\PyCharm\pythonProject\practice.py", line 304, in f
return n * f(n - 1) - f(n - 2)
^^^^^^^^
File "D:\PyCharm\pythonProject\practice.py", line 304, in f
return n * f(n - 1) - f(n - 2)
^^^^^^^^
[Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded
Ответы (1 шт):
Previous line repeated 996 more times
Это означает, что при выводе трейса ошибки Питон сэкономил экраны вывода и не стал повторять одну и ту же строку вывода 999 раз, а вывел её только три раза и написал "ну и ещё 996 раз такая же строка должна была вывестись, но мне лениво было".
К глубине собственно рекурсии эта надпись имеет косвенное отношение. Поскольку в строке с print
вызова функция вызывается 3 раза, а внутри функции каждый раз рекурсивно ещё по 2 раза, да ещё lru_cache
сверху навешен, то сложно понять, сколько всего было вызовов. Кстати, глубина рекурсии тратится не только на собственно рекурсию, а на любой вызов функции в принципе. А декоратор - это тоже дополнительный вызов функции.
В общем, попробуйте убрать декоратор lru_cache
и посмотрите, что получится. Возможно, надпись будет уже гораздо ближе к выставленному вами лимиту.
P.S. А если вы хотите просто посчитать результат, то лимит рекурсии трогать не нужно, а нужно просто "прогреть кэш". Лимит рекурсии превышается из-за использования рекурсии и из-за того, что кэш всё время промахивается. Нужно просто наполнить кэш заранее и тогда промахов не будет и рекурсии фактически тоже не будет, значения будут браться сразу из кэша:
from functools import lru_cache
@lru_cache(None)
def f(n):
if n == 1:
return 1
if n == 2:
return 2
if n > 2:
return n * f(n - 1) - f(n - 2)
# "прогрев" кэша
for i in range(2025):
f(i)
# само вычисление
print(f(2024) + f(2020) - f(2019))
Вообще этот вопрос тут много раз уже поднимался на разные лады.