python生成器/迭代器的设计模式?(后退读取/总计数)



我正在编写一个python接口,它基本上是从一个数据库逐行构建的,将流发送到一个tcp套接字,另一个线程检查tcp响应并决定是否有错误响应,跳过某些流,然后从以前的流重试。

下面的伪代码,PK表示PrimaryKey。

基本上就像这个

def generate_msg(pk_start, pk_stop):
for x in db.query(pk>pk_startand pk<pk_stop):
yield pack_to_stream(x)

那么tcp套接字发送线程就像:

for msg in generate_msg(first_id, last_id):
socket.send(msg)

问题是,当tcp套接字read线程在响应中发现一些错误时,会返回msg的pk,因此我需要从pk重新启动迭代器

所以我的问题是:

  1. 迭代器的设计部分是什么,它可以向前和向后移动,尤其是使用数据库行游标
  2. 我可以在不读取整个列表的情况下首先获得迭代器的总数吗
  3. 对于我的场景,一般建议是什么

感谢

迭代程序旨在通过一次处理一个项目来节省内存,并且可能产生无限数量的项目。然而,由于它们的设计,如果不消耗整个迭代器,您通常无法知道它们的长度,而且通常不希望您能够引导它们。

也就是说,没有什么可以阻止您创建一个既可以用作迭代器又可以提供额外功能的自定义类。数据库游标就是这样一个类的典型例子;可以迭代光标以生成行,但也可以要求它提供行数(即序列的长度),并通过调用.execute()方法获取有关列的附加信息、获取多行或指向新的结果集。

如果你想构建一个充当迭代器的自定义类,你需要给它一个__iter__()方法。您可以将此方法制作成生成器(通过使用yield语句),也可以只使用return self并为类提供.next()方法;后者期望返回一个项目(不要使用yield)或在不能返回更多项目时引发StopIteration

然后,您可以添加其他返回长度信息的方法,或者将查询重新设置为从给定主键开始。

未测试的python代码:

class MessagesIterator(object):
def __init__(self, pk_start, pk_stop):
self.pk_start, self.pk_stop = pk_start, pk_stop
self.cursor = db.query("pk>? and pk<?", (pk_start, pk_stop))
def __iter__(self):
return self
def next(self):
return next(self.cursor)  # raises StopIteration when done
def length(self):
return self.cursor.rowcount
def move_to(self, pk_start):
# Validate pk_start perhaps
self.pk_start = pk_start
self.cursor = db.query("pk>? and pk<?", (self.pk_start, self.pk_stop))

最新更新