【问题标题】:How to define an iterator class for my class?如何为我的类定义一个迭代器类?
【发布时间】:2021-08-17 14:05:37
【问题描述】:

我创建了一个包装类Graph,在其中创建了基于networkx 的图表。然而,这个类的对象是不可迭代的。为了解决这个问题,我知道我必须为我的Graph 类定义__iter__() 函数,其中调用了一个迭代器类的实例,比如GraphIterator。我刚刚检查了各种__next__() 函数的一些示例,虽然我不知道我应该如何定义我的班级的__next__() 函数。任何帮助将不胜感激。

import networkx as nx
import matplotlib.pyplot as plt

class Graph():
    def __init__(self, nodes=None, raw_edges=None, source_node=None, target_node=None):
        G = nx.Graph(source_node=None, target_node=None)
        G.add_nodes_from(nodes)
        G.add_edges_from([self.create_edge(raw_edge) for raw_edge in raw_edges])
        G.graph["source_node"] = self.assign_source_node(source_node, G.nodes)
        G.graph["target_node"] = self.assign_target_node(target_node, G.nodes)

    def __iter__(self):
        return GraphIterator(self)

    def create_edge(self, raw_edge):
        return [raw_edge[0], raw_edge[1], {'attr': raw_edge[2]}]

    def assign_source_node(self, source_node, node_list):
        if (int(source_node) in node_list):
            return source_node
        else:
            raise ValueError("Source node assignnmet is problematic!")

    def assign_target_node(self, target_node, node_list):
        if (int(target_node) in node_list):
            return target_node
        else:
            raise ValueError("Target node assignnmet is problematic!")


class GraphIterator:
   def __init__(self, graph):
       self._graph = graph
       self._index = 0
   def __next__(self):
       pass

def main():
    nodes = [1,2,3]
    raw_edges = [[1,2,1],[1,3,1],[2,3,1]]
    source_node = "1"
    target_node = "3"

    graph = Graph(nodes, raw_edges, source_node, target_node)

    nx.draw(graph, with_labels=True, font_weight="bold")
    plt.show()

if __name__ == "__main__":
    main()

【问题讨论】:

  • networkx Graph 不是已经provide an iterator?
  • @Mark:链接说它遍历节点(我想不是边)。同样,我不知道如何在我的上下文中使用它。
  • 如果您需要遍历边缘,for edge in G.edges 可以。
  • 另外,您可能应该阅读有关生成器的信息。手动编写迭代器很少是最好的选择。

标签: python iterator networkx


【解决方案1】:

这是一个简单的迭代器。这并没有将 GraphIterator 定义为一个单独的类,但也许它会有所帮助。真的下一个只需要返回任何你想要的迭代器。再简单不过了!在这种情况下,我猜你想返回一个node

class Graph():
    def __init__(self, stingfile):
        self.ix = 0
        self.nodes = [...]
    
    def __iter__(self):
        self.ix = 0
        return self
    
    def __next__(self):
        try:
            node = self.nodes[self.ix]
            self.ix += 1
            return node
        except IndexError:
            raise StopIteration

正如评论所说,looks like 它确实提供了一个迭代器!

节点字典上的iter 将连续返回每个键。这是一个简单的例子。这就是您使用的库返回节点的方式。

>>> a = iter({'a': 1, 'b':2, 'c':3, 'd':4})
>>> a
<dict_keyiterator object at 0x108bcb130>
>>> next(a)
'a'
>>> next(a)
'b'
>>> next(a)
'c'
>>> next(a)
'd'

【讨论】:

  • 这会破坏同一个图上的嵌套循环或多个线程中的并行使用等内容。
  • 正在展示如何构建一个简单的迭代器,以及如何实现 next 哈哈。 networkx 的 Graph 已经提供了一个迭代器作为我已经阐明的评论
  • 如果你想展示它,你应该通过编写一个单独的迭代器类而不是让 __iter____next__ 改变被迭代的对象来正确地展示它。
  • 也许你可以留下那个答案。你可以从这个复制和粘贴代码,如果它更容易离开它stackoverflow.com/a/64577267/5180047
猜你喜欢
  • 2012-07-14
  • 2020-01-03
  • 2020-09-27
  • 2017-04-16
  • 1970-01-01
  • 2020-12-04
  • 2014-12-31
  • 2011-07-08
  • 1970-01-01
相关资源
最近更新 更多