用Python生成器替换c++ STL输出迭代器
Replacing C++ STL output iterator with a Python generator
Python没有内置的OutputIterator;特别是,内置或标准库容器不支持任何允许客户端代码在不知道特定容器类型的情况下向它们发送数据的通用接口。
根据@Steven Rumbalski的评论和@Glenn Maynard的回答,这通常不是一个问题,因为在c++中会接受OutputIterator参数的函数,在python中会被简单地写为生成器。
通常情况下,我使用生成器没有问题,并且从来没有觉得我需要在Python中使用OutputIterator。然而,在这种情况下,我被卡住了。
我在Python中重新实现了Boost Graph Library中的一些算法。一个典型的图遍历算法,比如depth_first_search
,将一个"访问者"对象作为参数。访问者本质上是一堆回调函数,遍历算法在执行过程中遇到不同的事件(例如,发现一个新的顶点,检查一条边等)时会调用这些回调函数。在c++中,我可以让一个或几个这样的回调函数将数据发送到访问者对象在初始化时从客户机代码获得的OutputIterator对象。(例如,这正是topological_sort
是如何实现的:它接受一个OutputIterator,将其传递给dfs_visitor
对象,然后访问者对象"监视"事件finished_vertex
并将它接收到的顶点发送到指定的OutputIterator。当然,更复杂的情况需要多个OutputIterator对象和多个回调函数。
如何使用Python生成器实现相同的功能?
我需要以某种方式发送数据,在生成器"样式"中,从depth_first_search
到多个指定的数据消费者。我只是不知道该怎么做。(我使用Python 3.3.)
你能传递回调函数吗?
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':
# ...
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)
...
# this raises GeneratorExit at the `yield` in the generator
edge_consumer.close()
vertex_consumer.close()
def edge_handler():
while True:
e = yield
print "E", e
def vertex_handler():
while True:
v = yield
print "V", v
depth_first_search(..., edge_handler(), vertex_handler())
我不知道这是否可行,但是使用像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,幸运的是,仍然在我的浏览器缓存)。所以我恐怕这个答案太笼统了,细节太少了,但希望它至少能给你指明一个有用的方向。
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 在C应用程序中运行C++(带有STL)函数
- 使用2个键的cpp-stl::优先级队列排序不正确
- 在STL容器中使用模板类
- 用C++中的CPerson(类)类型的对象初始化STL矢量
- 将stl字符串缩小到小于15个字符的容量
- 在为LINUX创建共享库时,如何避免STL的私有/弱副本
- 检查函数返回类型是否与STL容器类型值相同
- STL算法函数在多个一维容器上的使用
- 在STL - C++中按成绩对学生列表进行排序?
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- λ可以适应STL吗?
- 为什么使用 NDK 不能存在不同的 stl 实现?
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 使用 char 分隔符解析C++中的字符串,但将可重复的字符保留为每个解析的子字符串 (C++ STL) 中的分隔符
- 在C++中迭代 STL 集时出现奇怪的问题<CStudent>
- 如何在 C++17 STL 并行算法中处理调度?
- 在学习数据结构之前对STL有一个了解是好的吗?
- C++ STL 排序会检查 NaN 吗?