如何使MyList可迭代?

时间:2015-09-13 18:57:45

标签: python list class functional-programming nodes

我想创建一个行为类似于列表的类。挑战在于不使用列表或字典。到目前为止,我已经创建了一个如下所示的节点类:

class Node:

    def __init__(self, value=None):
        self.next = None
        self.last = None
        self.value = valor

    def __repr__(self):
        return self.value

MyList类基本上是一个节点链,具有头节点和尾节点。事情是,我想让它可迭代,所以我可以用它运行for。我搜索了它和下一个如何工作并想出了类似的东西:

class MyList:

    def __init__(self):
        self.head = None
        self.tail = None

    def __iter__(self):
        return self

    def __next__(self):
        if self.head:
            if self.head.next:
                self.head = self.head.next
                return self.head.last
            aux = self.head
            self.head = None
            return aux
        raise StopIteration

它有效,但它显然删除了MyList中的数据,因此我无法再次使用它。关于如何在不弄乱对象内部信息的情况下获得相同结果的任何建议?

2 个答案:

答案 0 :(得分:6)

请注意,迭代器协议只要求the container's __iter__返回迭代器;您还可以将__iter__实现为生成器,而不是返回实例本身:

def __iter__(self):
    node = self.head
    while node is not None:
        yield node
        node = node.next

答案 1 :(得分:1)

您需要在类中添加“当前”标记,以指示迭代当前指向的节点。像这样:

class MyList:

    def __init__(self):
        self.head = None
        self.tail = None
        self.current = self.head

    def __iter__(self):
        return self

    def __next__(self):
        if self.current is not None:
            it = self.current
            self.current = self.current.next
            return it
        raise StopIteration

现在,你的列表不区分它的头部和当前的迭代位置,但这是两个完全不同的概念。

当然,如果你这样做,同一个MyList上的所有迭代都将被“链接”,所以如果你这样做:

x = MyList(1, 2, 3, 4)
for item in x:
    print(x)
    if item == 2:
        break

for item in x:
    print(x)

然后第二次迭代将从第一次离开的地方开始。如果您不想要这种行为,则必须创建一个单独的迭代器类,并让MyList.__iter__返回该实例,而不是self。如果从self返回__iter__,则对象不能进行多次独立迭代,因为迭代状态作为迭代数据存储在对象中。