首页 文章

用Python生成器替换C STL输出迭代器

提问于
浏览
1

Python没有内置的OutputIterator等价物;特别是,内置或标准库容器不支持允许客户端代码在不知道特定容器类型的情况下向其发送数据的任何通用接口 .

根据@Steven Rumbalski's comment@Glenn Maynard's answer,这通常不是问题,因为在C中的一个函数将在python中采用OutputIterator参数,它将被简单地写为生成器 .

通常,我使用生成器没有问题,从来没有觉得我需要Python中的OutputIterator . 然而,在这一例中,我被困住了 .

我在Python中重新实现了Boost Graph Library中的一些算法 . 典型的图遍历算法,例如 depth_first_search ,将"visitor"对象作为参数 . 访问者本质上是一组回调函数,遍历算法在执行时遇到不同的事件(例如,发现新的顶点,检查边缘等) . 在C中,我可以让一个或多个这些回调函数将数据发送到访问者对象在初始化时从客户端代码获得的OutputIterator对象 . (例如,正是如何实现 topological_sort :它需要一个OutputIterator,将它传递给 dfs_visitor 对象,访问者对象然后"monitors"事件 finished_vertex 并将它接收的顶点发送到指定的OutputIterator . 当然,更复杂的情况需要多个OutputIterator对象和多个回调函数 . )

如何使用Python生成器实现相同的目标?

我需要以某种方式将生成器_808636中的数据从 depth_first_search 发送到多个指定的数据使用者 . 我只能't figure out how to do it. (I'使用Python 3.3 . )

3 回答

  • 1

    你能通过回调函数吗?

    def depth_first_search(some_args, on_edge=lambda e:None, on_vertex=lambda v:None):
        ...
        on_edge(some_edge)
        on_vertex(some_vertex)
    
    def edge_handler(e):
        print "E", e
    
    def vertex_handler(v):
        print "V", v
    
    depth_first_search(..., on_edge=edge_handler, on_vertex=vertex_handler)
    

    或者产生一个目的地:

    def depth_first_search(some_args, on_edge=lambda e:None, on_vertex=lambda v:None):
        ...
        yield "edge", some_edge
        yield "vertex", some_vertex
    
    for t, value in depth_first_search(...):
        if t == 'edge':
            # ...
        elif t == 'vertex':
            # ...
    
  • 1

    generator.send方法在这里做你想要的,我想:

    def depth_first_search(some_args, edge_consumer, vertex_consumer):
        # start the generators
        next(edge_consumer)
        next(vertex_consumer)
    
        ...
        edge_consumer.send(some_edge)
        vertex_consumer.send(some_vertex)
    
        ...
        edge_consumer.close()
        vertex_consumer.close()
    
    def edge_handler():
        try:
            while True:
                e = yield
                print "E", e
        except GeneratorExit:
            return
    
    def vertex_handler():
        try:
            while True:
                v = yield
                print "V", v
        except GeneratorExit:
            return
    
    
    depth_first_search(..., edge_handler(), vertex_handler())
    
  • 0

    我不知道这是否可行,但是如何使用像multimethods这样的库来实现多调度功能来满足您的需求呢?我的互联网存在DNS问题所以我无法查找语法,因此您将获得伪代码而不是真正的Python,但这里是我所谈论的一般概念:

    def send_to(data, consumer):
        workfunc = dispatch(type(consumer))
        workfunc(data, consumer)
    
    def send_to_list(data, consumer):
        consumer.append(data)
    
    def send_to_set(data, consumer):
        consumer.add(data)
    
    def send_to_file_obj(data, consumer):
        consumer.write(data)
    

    当然,需要一些管道来将工作函数连接到调度函数,而这正是我现在无法查找的,因为我的DNS已关闭 . (幸运的是,StackOverflow仍然在我的浏览器缓存中) . 因此,我担心这个答案很长,一般性和具体细节,但希望它至少会指向你一个有用的方向 .

相关问题