避免使用圆参考的RuntimeError

时间:2016-12-30 10:03:20

标签: python recursion

我有以下代码:

class Cell(object):
    def eval(self):
        raise NotImplementedError


class RefCell(Cell):
    def __init__(self, cell=None):
        self.next_cell = cell

    def set_next(self, cell):
        self.next_cell = cell
        if self.next_cell:
            try:
                check = self.next_cell.eval()
            except AttributeError:
                pass
            else:
                if check == self:
                    raise Exception

    def eval(self):
        return self.next_cell.eval()


c1 = RefCell()
c2 = RefCell()
c3 = RefCell()
c4 = RefCell()

c1.set_next(c2)
c2.set_next(c3)
c3.set_next(c4)
c4.set_next(c2)

我正试图避免在以下情况下遇到的RuntimeError:

c4.set_next(c2)

但是我无法弄清楚我可以捕获圆引用并抛出我的泛型异常的方式,而是我遇到了这个:

RuntimeError: maximum recursion depth exceeded while calling a Python object

我会很感激。

2 个答案:

答案 0 :(得分:1)

您可以保存通过后续调用eval处理的节点的历史记录,并检查您是否在处理节点之前访问过该节点。

def eval(self, history=None):
    if history and self in history:
        raise Exception
    # put eval logic here
    history = history or {}
    history.add(self)
    self.next_cell.eval(history)

答案 1 :(得分:0)

如果调用了单元格eval()函数,也许你可以引入一个默认为False的属性设置为true。然后让eval函数引发异常:

def eval(self):
    self.evaluated=True
    if self.next_cell.evaluated:
        raise Exception
    return self.next_cell.eval()

我没有尝试过,但我觉得应该可行。我也不确定是否需要返回语句,因为我不知道稍后你的脚本会发生什么。

当然,您下次尝试评估时需要重置该属性...这有点不方便。