如何在Python中检查容器类型对象的循环引用

时间:2016-03-04 09:57:57

标签: python garbage-collection

我想实现一个程序来检查容器类型的对象中是否存在循环引用。幸运的是,我在 pymotw

中找到了一个简短的程序

我在这里粘贴了源代码,但它似乎是错误的,就像文章底部的评论所说的那样。

我可以根据源代码实现正确的版本吗?

import gc
import pprint
import Queue

class Graph(object):
    def __init__(self, name):
        self.name = name
        self.next = None
    def set_next(self, next):
        print 'Linking nodes %s.next = %s' % (self, next)
        self.next = next
    def __repr__(self):
        return '%s(%s)' % (self.__class__.__name__, self.name)

# Construct a graph cycle
one = Graph('one')
two = Graph('two')
three = Graph('three')
one.set_next(two)
two.set_next(three)
three.set_next(one)

print

seen = set()
to_process = Queue.Queue()

# Start with an empty object chain and Graph three.
to_process.put( ([], three) )

# Look for cycles, building the object chain for each object we find
# in the queue so we can print the full cycle when we're done.
while not to_process.empty():
    chain, next = to_process.get()
    chain = chain[:]
    chain.append(next)
    print 'Examining:', repr(next)
    seen.add(id(next))
    for r in gc.get_referents(next):
        if isinstance(r, basestring) or isinstance(r, type):
            # Ignore strings and classes
            pass
        elif id(r) in seen:
            print
            print 'Found a cycle to %s:' % r
            for i, link in enumerate(chain):
                print '  %d: ' % i,
                pprint.pprint(link)
        else:
            to_process.put( (chain, r) )

1 个答案:

答案 0 :(得分:0)

算法如下:

{{1}}

您实现了Queu的代码,因此您必须修改它以适应Queu架构。但无论如何,算法都保持正确:

  1. 如果我已经访问了节点并且它与第一个节点相同,我找到了一个路径,如果它与第一个节点不一样,我继续(返回),因为我可能有一个循环。
  2. 我将当前节点设置为visited = YES
  3. 对于我所在的每个相邻节点,我递归地调用此函数与邻近节点,子节点和起始节点的子节点。
  4. 然后我设置了visited = NO。因为如果我到达结束时节点没有邻接(所以结束)因此它不是我正在寻找的当前周期的一部分而且我回溯所以它就好像我没有去过那里。