1 回答
![?](http://img1.sycdn.imooc.com/5458472300015f4702200220-100-100.jpg)
TA贡献1836条经验 获得超13个赞
下一项的 dunder 方法不是__next__,__next并且您似乎缺少在迭代时实际在列表中移动的代码。
我使用的常规方法是在类型中使用一个单独的迭代器类来完成繁重的工作。此外,设置列表的方式也使得元素类的想法变得可取(如果您使用Python列表,则不需要这样做,但是,由于您需要一个and“指针”,所以最好将其作为单独的item列表next)班级)。
让我们首先创建带有封闭项目类的列表类:
class MyList:
# Single element in the list.
class MyListElem:
def __init__(self, item, link_from = None, link_to = None):
# Set data, link from previous and to next if specified.
self._item = item
self._next = link_to
if link_from is not None:
link_from.change_link(self)
def change_link(self, item):
self._next = item
元素类有两种方法,第一种方法根据需要创建带有链接的元素。目前(见MyList.add()下文),to链接始终是None因为我们仅附加到列表中。
类似地,from链接要么是None当前尾部,要么是当前尾部,具体取决于我们是将第一个元素还是后续元素添加到列表中。
这些参数主要是为了满足以后能够插入列表中任意位置的可能性。
接下来是迭代器类,也是列表类的一部分:
# Iterator over the list.
class MyListIter:
def __init__(self, head):
# Start at the head.
self._curr = head
def __iter__(self):
# To iterate over the iterator rather than collection.
return self
def __next__(self):
# Check more left, advance to next and return current.
if self._curr is None:
raise StopIteration
ret_val = self._curr._item
self._curr = self._curr._next
return ret_val
这相对简单,初始化器只是设置我们以便第一次调用将返回头部。该__iter__调用允许您从集合中检索迭代器,然后对其进行迭代,而不是直接在集合上进行迭代。区别在于:
for iter in object: # iterate over object
pass
iter = object.__iter__() # iterate over iterator
for iter2 in iter:
pass
有关为什么需要这样做的更多详细信息,请参阅此处。
调用__next__是迭代器的“核心”。如果迭代器完成,它会引发异常。否则,它会在前进到下一个值后返回当前值。
然后是列表类本身,一个非常简单的类,只允许追加到末尾,不允许删除,并且有一个迭代器来处理它:
# The list itself.
def __init__(self):
# Empty list to start with.
self._head = None
self._tail = None
def add(self, val):
# Append to the end of the list.
if self._head is None:
self._head = self.MyListElem(val)
self._tail = self._head
else:
self._tail = self.MyListElem(val, self._tail)
def __iter__(self):
return self.MyListIter(self._head)
这真的很容易(嗯,相对容易)。以下测试代码显示了它的实际效果:
x = MyList()
x.add(12345)
x.add(42)
x.add("Hello")
x.add([1, 2, 3])
for i in x:
print(i)
正如预期的那样,其输出是:
12345
42
Hello
[1, 2, 3]
添加回答
举报