Ich überarbeite ein Python-Signalverarbeitungsframework wegen eines maximalen Wiederholungstiefefehlers, den wir erfahren haben.Ist Python maximale Wiederholungstiefe pro Objekt?
Die wahrscheinlichste Erklärung für den Fehler ist, dass manchmal eine große Anzahl von Instanzen einer einzelnen Klasse rekursiv aus der Klasse 'init Methode erstellt wird. In der Tat führen Experimente, die diese Situation simulieren, zu einem Exception RuntimeError: "Maximale Rekursionstiefe überschritten".
Wenn ich das nächste Element in der Kette zu dem Container verschiebe, der diese Objekte verwaltet, scheint das Problem zu verschwinden, obwohl dies in meinem naiven Verständnis einen Call-Stack von gleicher Tiefe erzeugt. Ich rufe Create über alle zuvor erstellten Objekte auf. (siehe Beispielcode).
Ich neige zu der Schlussfolgerung, dass die Rekursionstiefe Grenze irgendwie pro Objekt (sei es eine Klasse oder eine Instanz) festgelegt ist. Was beim rekursiven Erzeugen über init wahrscheinlich alles auf den Stack der Klasse stellt, wobei wir, als ob wir sie rekursiv durch eine Reihe von Instanzen derselben Klasse erzeugen würden, alle Objekte eine sehr begrenzte Rekursionstiefe hätten.
Ich suche eine Bestätigung für diese Hypothese, aber finde es schwierig, entweder Bestätigung oder Widerlegung zu erhalten.
import sys
class Chunk(object):
pre=None
post=None
def __init__(self, container,pre):
print 'Chunk Created'
self.pre=pre
self.container=container
def create(self,x):
if self.post == None:
self.post=Chunk(self.container,self)
newChunk =self.post
else:
newChunk =self.post.create(x+1)
return newChunk
def droprefs(self):
print 'refcount droprefs start: ', sys.getrefcount(self)
if not self.pre ==None:
self.pre.droprefs()
self.pre=None
self.post=None
self.container=None
print 'refcount droprefs end: ', sys.getrefcount(self)
def claimContainer(self):
self.container.setmasterchunk(self)
self.pre.droprefs()
self.pre=None
class Container(object):
masterchunk=None
def __init__(self):
self.masterchunk=Chunk(self, None)
def setmasterchunk(self, chunk):
print 'refcount 5: ', sys.getrefcount(self.masterchunk)
self.masterchunk=chunk
print 'refcount 6: ', sys.getrefcount(self.masterchunk)
def testrecursion(self,n):
for i in range(n):
print 'refcount 6: ', sys.getrefcount(self.masterchunk)
newChunk=self.masterchunk.create(1)
return newChunk
def testhistoryremoval(self,chunk):
chunk.claimContainer()
if __name__ == '__main__':
C=Container()
middle=C.testrecursion(300)
last=C.testrecursion(600)
last=C.testhistoryremoval(middle)
if middle== C.masterchunk:
print 'SUCCESS'
Anmerkung hinzugefügt:
-Code die maximale Rekursionstiefe zeigt:
import sys
from time import sleep
class Chunk(object):
pre=None
post=None
def __init__(self, container,pre,n):
print 'Chunk Created'
self.pre=pre
self.container=container
if n>0:
self.post=Chunk(self.container,self,n-1)
def droprefs(self):
print 'refcount droprefs start: ', sys.getrefcount(self)
if not self.pre ==None:
self.pre.droprefs()
self.pre=None
self.post=None
self.container=None
print 'refcount droprefs end: ', sys.getrefcount(self)
def claimContainer(self):
self.container.setmasterchunk(self)
self.pre.droprefs()
self.pre=None
class Container(object):
masterchunk=None
def __init__(self):
pass
def setmasterchunk(self, chunk):
print 'refcount 5: ', sys.getrefcount(self.masterchunk)
self.masterchunk=chunk
print 'refcount 6: ', sys.getrefcount(self.masterchunk)
def testrecursion(self,n):
self.masterchunk=Chunk(self,None,n)
if __name__ == '__main__':
print('Try 10')
C0=Container()
C0.testrecursion(10)
sleep(2)
print('Try 1000')
C1=Container()
C1.testrecursion(1000)
"Wenn ich das nächste Element in der Kette zum Container verschiebe, der diese Objekte verwaltet, scheint das Problem zu verschwinden" - höchstwahrscheinlich, weil Sie nicht mehr rekursiv sind oder weniger rekursiv sind. – user2357112
Sie können die Rekursionstiefe ändern. Es gibt einen Algorithmus, der es basierend auf der Leistung Ihres Computers für Sie berechnet. – noumenal
Related: http://StackOverflow.com/A/26873813/2289509 – Elazar