【发布时间】:2016-12-11 05:08:52
【问题描述】:
我正在重构 Python 信号处理框架,因为我们遇到了最大重复深度错误。
对该错误最可能的解释是,有时单个类的大量实例是从类的 init 方法递归创建的。事实上,模拟这种情况的实验会导致异常 RuntimeError: 'maximum recursion depth exceeded'。
当我将链中的下一个元素创建到管理这些对象的容器时,问题似乎消失了,尽管在我天真的理解中构建了相同深度的调用堆栈。我通过所有以前创建的对象调用创建。 (见示例代码)。
我倾向于得出结论,递归深度限制是以某种方式为每个对象设置的(无论是类还是实例)。当通过 init 递归创建时,可能会将所有内容放在类的堆栈中,就好像我们通过同一类的一系列实例递归创建它们一样,所有对象的递归深度都非常有限。
我正在为这个假设寻求一些证实,但发现很难得到证实或反驳。
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'
补充说明:
显示最大递归深度的代码:
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)
【问题讨论】:
-
“当我将链中的下一个元素创建到管理这些对象的容器中时,问题似乎消失了”——很可能是因为您不再递归,或者递归的深度不够。
-
您可以更改递归深度。有一种算法可以根据您计算机的性能为您计算它。
-
信号处理不是计算密集型的吗?如果是这样,递归似乎不合适。
-
@Elazar 信号处理是计算密集型的,但我所针对的代码是将传入信息放在正确位置的机制,它先于实际的信号处理。完成并发布后,如果您有兴趣,我可以在此处发布更新。