【发布时间】:2015-07-28 18:28:10
【问题描述】:
在尝试实现迭代器时,我对 next() 感到困惑。我制作了一个简单的测试脚本,其中迭代器按预期工作:
class Object:
def __init__(self, name):
self.name = name
def prin(self):
print self.name
class Some:
def __init__(self):
self.data = list()
def __iter__(self):
return self.SomeIter(self, len(self.data))
def fill(self, obj):
self.data.append(obj)
def printMe(self):
for entry in self:
print entry.name
class SomeIter:
def __init__(self, some, end):
self.index = 0
self.end = end
self.name = some.data[self.index].name
self.data = some.data
def next(self):
if self.index == self.end:
raise StopIteration
else:
self.name = self.data[self.index].name
self.index += 1
return self
########################################################################
someX = Some()
obj1 = Object("A")
obj2 = Object("B")
someX.fill(obj1)
someX.fill(obj2)
someX.fill(obj2)
for obj in someX:
print obj.name
我得到“A B B”作为输出。这都很好。但是我也有一个树类的迭代器。 next() 方法的工作原理基本相同。我首先更新实例然后返回它。但是在树迭代器的情况下,第一个元素被跳过。这对我来说很有意义,因为我只有在更新实例后才返回 self 。但是为什么在上述实现的情况下我会得到不同的行为,实例正在更新,然后才返回呢?
########################################################################
# RIGHT-HAND-CORNER-BOTTOM-UP-POST-ORDER-TRAVERSAL-ITERATOR
########################################################################
class RBPIter:
"""!
@brief Right hand corner initialised iterator, traverses tree bottom
up, right to left
"""
def __init__(self, tree):
self.current = tree.get_leaves(tree.root)[-1] # last leaf is right corner
self.csi = len(self.current.sucs)-1 # right most index of sucs
self.visited = list() # visisted nodes
self.tree = tree
self.label = self.current.label
########################################################################
def __iter__(self):
return self
########################################################################
def begin(self):
return self.tree.get_leaves(self.tree.root)[-1]
########################################################################
def end(self):
return self.tree.root
########################################################################
def find_unvisited(self, node):
"""!
@brief finds rightmost unvisited node transitively dominated by node
"""
leaves = self.tree.get_leaves(self.tree.root)
# loop through leaves from right to left, as leaves are listed
# in order, thus rightmost list elememt is rightmost leaf
for i in range(len(leaves)-1, -1, -1):
# return the first leaf, that has not been visited yet
if leaves[i] not in self.visited:
self.label = leaves[i].label
return leaves[i]
# return None if all leaves have been visited
return None
########################################################################
def go_up(self, node):
"""!
@brief sets self.current to pred of self.current,
appends current node to visited nodes, reassignes csi
"""
self.visited.append(self.current)
self.current = self.current.pred
if self.current.sucs[0] not in self.visited:
self.current = self.find_unvisited(self.current)
self.label = self.current.label
self.csi = len(self.current.sucs)-1
self.visited.append(self.current)
########################################################################
def next(self):
"""!
@brief advances iterator
"""
# if current node is a leaf, go to its predecessor
if self.current.suc_count == 0 or self.current in self.visited:
self.go_up(self.current)
# if current node is not a leaf, find the next unvisited
else:
self.current = self.find_unvisited(self.current)
if self.current == self.end():
raise StopIteration
return self
编辑 1:
我比较了两个迭代器的输出,它们不同,SomeIter 输出第一个元素 2 次:
next: A
A
next: A
B
next: B
B
next: B
另一个迭代器没有:
next: a
s
next: s
i
next: i
r
next: r
t
next: t
t
next: t
s
next: s
e
next: e
t
next: t
否则 "next: a" 会出现 2 次p>
编辑 2:
这对我来说真的没有任何意义......
查看这些调用和输出:
someXIter = iter(someX)
print someXIter.next().name
print someXIter.next().name
print someXIter.next().name
输出:
next: A
A
next: A
B
next: B
B
使用此代码:
class SomeIter:
def __init__(self, some, end):
self.index = 0
self.end = end
self.name = some.data[self.index].name
self.data = some.data
def next(self):
print "next: ", self.name
if self.index == self.end:
raise StopIteration
else:
self.name = self.data[self.index].name
self.index += 1
return self
为什么这对我来说毫无意义?因为,第一次调用 next() 时,它会打印“next: A”,然后更新实例,并打印函数调用的返回值,也就是“A”。哇?为什么不是“B”,返回值应该是更新后的实例。
【问题讨论】:
-
您能否尽量减少代码量来重现您的问题? stackoverflow.com/help/mcve
-
但是第一段代码已经是一个最小化的例子了... ?它也包含执行代码。输出也在我的帖子中。我不明白你想让我怎么把它最小化。
-
为什么将
SomeIter实现为一个类? -
一是因为我认为迭代器必须是对象,二是因为我在实际程序中需要多个迭代器。
-
您是否对
next或您的实现感到困惑?next应该返回下一项并在用尽时提高StopIteration。哪个版本的 Python?为什么不使用 new-style 类?