0

我正在编写一个 python 接口,它基本上从一个 db 逐行构造,将流发送到 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 socketread线程在响应中发现一些错误时,返回了 msg 的 pk,所以我需要从pk

所以这是我的问题:

  1. 可以向前和向后移动的迭代器的设计模式是什么,尤其是。使用数据库行游标
  2. 我可以在不阅读整个列表的情况下首先获得迭代器的总数吗?
  3. 我的方案的一般建议是什么?

谢谢

4

1 回答 1

1

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

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

如果你想构建一个作为迭代器的自定义类,你需要给它一个__iter__()方法。你要么把这个方法变成一个生成器(通过使用yield语句),或者只是return self给你的类一个.next()方法;后者预计会退回一件物品(不要使用yield),或者StopIteration在无法退回更多物品时提出。

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

未经测试的python-ish代码:

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))
于 2012-11-23T09:05:53.727 回答