Почему существует RecursionError [duplicate]

Эта ошибка возникает, когда ваш экземпляр сервера sql stopped.

Перейдите ко всем программам> SQL Server> Инструменты настройки> МЕНЕДЖЕР КОНФИГУРАЦИИ SQL SERVER

, затем нажмите кнопку SQL sERVER Службы, список экземпляров появится, выберите интересующий экземпляр и нажмите значок воспроизведения на верхней панели инструментов, надеюсь, что это поможет.

этот ответ очень поздний (но лучше поздно, чем никогда;)

229
задан Ciro Santilli 新疆改造中心 六四事件 法轮功 29 January 2017 в 00:41
поделиться

13 ответов

Это защита от переполнения стека, да. Python (вернее, реализация CPython) не оптимизирует хвостовую рекурсию, а необузданная рекурсия вызывает переполнение стека. Вы можете изменить предел рекурсии на sys.setrecursionlimit , но это опасно - стандартный предел немного консервативен, но стековые структуры Python могут быть довольно большими.

Python isn Функциональный язык и рекурсия хвоста не являются особенно эффективным методом. Переписывание алгоритма итеративно, если это возможно, обычно является лучшей идеей.

272
ответ дан Day 18 August 2018 в 12:15
поделиться

Использовать генераторы?

def fib():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fibs = fib() #seems to be the only way to get the following line to work is to
             #assign the infinite generator to a variable

f = [fibs.next() for x in xrange(1001)]

for num in f:
        print num

выше функция fib (), адаптированная из: http://intermediatepythonista.com/python-generators

4
ответ дан alex 18 August 2018 в 12:15
поделиться
  • 1
    причина того, что нужно назначить генератор переменной, состоит в том, что [fibs().next() for ...] каждый раз создавал новый генератор. – tox123 10 August 2016 в 19:02

Если вы хотите получить только несколько чисел Фибоначчи, вы можете использовать матричный метод.

from numpy import matrix

def fib(n):
    return (matrix('0 1; 1 1', dtype='object') ** n).item(1)

Это быстро, поскольку numpy использует алгоритм быстрого возведения в степень. Вы получаете ответ в O (log n). И это лучше, чем формула Бине, потому что она использует только целые числа. Но если вы хотите, чтобы все числа Фибоначчи были до n, тогда лучше сделать это путем запоминания.

3
ответ дан bebidek 18 August 2018 в 12:15
поделиться
  • 1
    К сожалению, вы не можете использовать numpy в большинстве конкурирующих судей по программированию. Но да, сэр, ваше решение - мой любимый. Я использовал матриксное решение для некоторых проблем. Это лучшее решение, когда вам нужно очень большое число фибоначчи, и вы не можете использовать модуль. Если вам разрешено использовать модуль, период pisano - лучший способ сделать это. – mentatkgs 9 June 2018 в 01:49

Многие рекомендуют, что увеличение предела рекурсии является хорошим решением, но это не потому, что всегда будет предел. Вместо этого используйте итерационное решение.

def fib(n):
    a,b = 1,1
    for i in range(n-1):
        a,b = b,a+b
    return a
print fib(5)
1
ответ дан Christopher Hackett 18 August 2018 в 12:15
поделиться

resource.setrlimit также необходимо использовать для увеличения размера стека и предотвращения segfault

Ядро Linux ограничивает стек процессов.

Python хранит локальные переменные в стеке интерпретатор, и поэтому рекурсия занимает пространство стека интерпретатора.

Если интерпретатор Python пытается преодолеть ограничение стека, ядро ​​Linux segfaults.

Размер ограничения стека равен управляется системными вызовами getrlimit и setrlimit.

Python предлагает доступ к этим системным вызовам через модуль resource.

import resource
import sys

print resource.getrlimit(resource.RLIMIT_STACK)
print sys.getrecursionlimit()
print

# Will segfault without this line.
resource.setrlimit(resource.RLIMIT_STACK, [0x10000000, resource.RLIM_INFINITY])
sys.setrecursionlimit(0x100000)

def f(i):
    print i
    sys.stdout.flush()
    f(i + 1)
f(0)

Конечно, если вы держите увеличивая уровень ulimit, ваша операционная система закончится, что либо остановит ваш компьютер на остановке из-за безумия подкачки, либо убьет Python через OOM Killer.

Из bash вы можете увидеть и установить ограничение стека ( в kb) с:

ulimit -s
ulimit -s 10000

Значение по умолчанию для меня равно 8Mb.

См. также:

Проверено на Ubuntu 16.10, Python 2.7.12.

5
ответ дан Ciro Santilli 新疆改造中心 六四事件 法轮功 18 August 2018 в 12:15
поделиться
  • 1
    Попытка установить rlimit_stack после исправлений Stack Clash может привести к сбою или связанным с этим проблемам. Также см. Red Hat Issue 1463241 – jww 21 June 2017 в 16:35

Так как @alex предложил , вы можете использовать функцию генератора для этого. Вот эквивалент кода в вашем вопросе:

def fib(n):
    def fibseq(n):
        """ Iteratively return the first n Fibonacci numbers, starting from 0 """
        a, b = 0, 1
        for _ in xrange(n):
            yield a
            a, b = b, a + b

    return sum(v for v in fibseq(n))

print format(fib(100000), ',d')  # -> no recursion depth error
1
ответ дан Community 18 August 2018 в 12:15
поделиться

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

def fibonacci(n):
    f = [0,1,1]
    for i in xrange(3,n):
        f.append(f[i-1] + f[i-2])
    return 'The %.0fth fibonacci number is: %.0f' % (n,f[-1])

(используйте n + 1 в xrange, если вы начинаете считать свою последовательность фибоначчи от 0 вместо 1.)

10
ответ дан Daniel 18 August 2018 в 12:15
поделиться
  • 1
    зачем использовать O (n) пространство, когда вы можете использовать O (1)? – Janus Troelsen 12 March 2014 в 11:11
  • 2
    На всякий случай комментарий в пространстве O (n) был путаным: не используйте список. Список сохранит все значения, когда все, что вам нужно, - это n-е значение. Простым алгоритмом было бы сохранить последние два числа фибоначчи и добавить их до тех пор, пока вы не получите тот, который вам нужен. Есть и лучшие алгоритмы. – Milimetric 14 July 2014 в 20:12
  • 3
    Также для тех, кто читает: xrange не работает в Python 3. – Mathime 18 June 2016 в 14:42
  • 4
    @Mathime: xrange называется просто range, в Python 3. – Eric Lebigot 3 August 2016 в 09:50
  • 5
    @Mathime Я делал вещи явным для тех, кто читал эти комментарии. – Eric Lebigot 3 August 2016 в 09:54

Похоже, вам просто нужно установить более высокую глубину рекурсии

sys.setrecursionlimit(1500)
71
ответ дан David Young 18 August 2018 в 12:15
поделиться

Если вам часто необходимо изменить предел рекурсии (например, при решении головоломок программирования), вы можете определить простой менеджер контекста следующим образом:

import sys

class recursionlimit:
    def __init__(self, limit):
        self.limit = limit
        self.old_limit = sys.getrecursionlimit()

    def __enter__(self):
        sys.setrecursionlimit(self.limit)

    def __exit__(self, type, value, tb):
        sys.setrecursionlimit(self.old_limit)

Затем, чтобы позвонить с пользовательским пределом, который вы можете сделать:

with recursionlimit(1500):
    print(fib(1000, 0))

При выходе из тела оператора with предел рекурсии будет восстановлен до значения по умолчанию.

1
ответ дан Eugene Yarmash 18 August 2018 в 12:15
поделиться

Используйте язык, который гарантирует оптимизацию хвостового вызова. Или используйте итерацию. В качестве альтернативы, получите милый с декораторами .

17
ответ дан Marcelo Cantos 18 August 2018 в 12:15
поделиться
  • 1
    Это довольно бросает ребенка с водой для ванны. – Russell Borogove 24 July 2010 в 01:09
  • 2
    @Russell: Только один из вариантов, которые я предложил, советует это. – Marcelo Cantos 24 July 2010 в 04:22

Конечно, числа Фибоначчи могут быть вычислены в O (n), применяя формулу Бине:

from math import floor, sqrt

def fib(n):                                                     
    return int(floor(((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))+0.5))

Как отмечают комментаторы, это не O (1), а O (n) из-за 2**n. Также разница в том, что вы получаете только одно значение, а при рекурсии вы получаете все значения Fibonacci(n) до этого значения.

9
ответ дан rwst 18 August 2018 в 12:15
поделиться
  • 1
    Максимального размера длинного в питоне нет. – ppperry 21 November 2015 в 19:14
  • 2
    Стоит отметить, что это не удается для больших n из-за неточности с плавающей запятой - разница между (1+sqrt(5))**n и (1+sqrt(5))**(n+1) становится меньше 1 ulp, поэтому вы начинаете получать неправильные результаты. – Mego 7 July 2016 в 14:02
  • 3
    В NumPy фактически нет больших целых чисел ... – Eric Lebigot 3 August 2016 в 09:52
  • 4
    @Mego Что? Это разница между (1+sqrt(5))**n и ((1+sqrt(5))**n)+1, которая становится меньше 1 ulp! (маленькая опечатка) Кроме того, {@} rwst Это не O (1)! Вычисление 2**n занимает не менее O (n) времени. – user202729 5 January 2018 в 02:43
  • 5
    @ user202729 Это неверно, вычисление 2**n - эффективно O (log (n)), используя Экспоненциальность, возведя квадрат . – Sam 18 February 2018 в 19:02

У меня была аналогичная проблема с ошибкой «Максимальная глубина рекурсии». Я обнаружил, что ошибка запускалась поврежденным файлом в каталоге, в котором я перебирал os.walk. Если у вас возникли проблемы с решением этой проблемы, и вы работаете с файловыми путями, обязательно сузите их, так как это может быть поврежденный файл.

7
ответ дан Tyler 18 August 2018 в 12:15
поделиться
  • 1
    ОП дает свой код, и его эксперимент воспроизводится по желанию. Это не связано с поврежденными файлами. – T. Verron 1 March 2015 в 20:25
  • 2
    Вы правы, но мой ответ не связан с OP, так как это было более четырех лет назад. Мой ответ направлен на то, чтобы помочь тем, у кого ошибки MRD косвенно вызваны поврежденными файлами, поскольку это один из первых результатов поиска. Это помогло кому-то, поскольку оно было проголосовано. Спасибо за пониженное голосование. – Tyler 2 March 2015 в 21:36
  • 3
    Это была единственная вещь, которую я нашел где-то, когда искал мою проблему, которая связана с глубиной рекурсии max. traceback к поврежденному файлу. Благодаря! – Jeff 18 July 2017 в 17:23

Во избежание переполнения стека. Интерпретатор Python ограничивает глубину рекурсии, чтобы помочь вам избежать бесконечных рекурсий, что приводит к переполнению стека. Попробуйте увеличить предел рекурсии (sys.setrecursionlimit) или переписать свой код без рекурсии.

из веб-сайта python :

sys.getrecursionlimit()

Возвращает текущее значение предела рекурсии, максимальную глубину стека интерпретатора Python. Этот предел предотвращает бесконечную рекурсию из-за переполнения стека C и сбой Python. Он может быть установлен setrecursionlimit ().

29
ответ дан user1248490 18 August 2018 в 12:15
поделиться
  • 1
    На моем Anaconda x64, 3.5 Python в Windows предел по умолчанию - 1000. – Guillaume Chevalier 4 December 2015 в 22:48
  • 2
    Мой лимит по умолчанию для окон также 1000, но 2000 - это установка Anaconda 3 x64 3.6 для моего Mac. Я думаю, что основным моментом является ограничение по умолчанию для разных установок. Тем не менее, это невероятно единственный ответ до недавнего времени, который на самом деле говорит вам, как проверить значение. Ответ с наивысшим разрешением даже не упоминает sys.getrecursionlimit(), и это было половиной исходного вопроса! – rob3c 3 November 2017 в 19:12
Другие вопросы по тегам:

Похожие вопросы: