第七章:数据持久存储与交换-pickle:对象串行化-循环引用

7.1.5 循环引用
pickle协议会自动处理对象之间的循环引用,所以复杂数据结构不需要任何特殊的处理。考虑图7-1中的有向图。这个图中包含几个环,不过仍然可以腌制所得的正确结构然后重新加载。
在这里插入图片描述

import pickle

class Node:
    """A simple digraph
    """
    def __init__(self,name):
        self.name = name
        self.connections = []

    def add_edge(self,node):
        "Create an edge between this node and the other."
        self.connections.append(node)

    def __iter__(self):
        return iter(self.connections)


def preorder_traversal(root,seen=None,parent=None):
    """Generator function to yield the edges in a graph.
    """
    if seen is None:
        seen = set()
    yield (parent,root)
    if root in seen:
        return
    seen.add(root)
    for node in root:
        recurse = preorder_traversal(node,seen,root)
        for parent,subnode in recurse:
            yield (parent,subnode)

def show_edges(root):
    "Print all the edges in the graph."
    for parent,child in preorder_traversal(root):
        if not parent:
            continue
        print('{:>5} -> {:>2} ({})'.format(
            parent.name,child.name,id(child)))

# Set up the nodes.
root = Node('root')
a = Node('a')
b = Node('b')
c = Node('c')

# Add edges between them.
root.add_edge(a)
root.add_edge(b)
a.add_edge(b)
b.add_edge(a)
b.add_edge(c)
a.add_edge(a)

print('ORIGINAL GRAPH:')
show_edges(root)

# Pickle and unpickle the graph to create
# a new set of nodes.
dumped = pickle.dumps(root)
reloaded = pickle.loads(dumped)

print('\nRELOADED GRAPH:')
show_edges(reloaded)

重新加载的节点并不是同一个对象,但保持了节点之间关系,而且如果对象有多个引用,那么只会重新加载这个对象的一个副本。要验证这两点,可以在通过pickle传递节点之前和之后检查节点的id()值。
运行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43193719/article/details/88804988
今日推荐