python-对next()和__iter __()的确切工作方式感到困惑
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python-对next()和__iter __()的确切工作方式感到困惑,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6522字,纯文字阅读大概需要10分钟。
内容图文
![python-对next()和__iter __()的确切工作方式感到困惑](/upload/InfoBanner/zyjiaocheng/662/6963c85e0e77470d99130232ee765f76.jpg)
在尝试实现迭代器时,我对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将第一个元素输出两次:
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次
编辑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”,因为返回值应该是更新的实例.
解决方法:
Python 2.7
要成为迭代器,必须实现迭代器协议:
>定义obj .__ iter__和obj.next
> obj .__ iter__必须返回self
>引发StopIteration后,对obj.next()(next(obj))的后续调用必须引发StopIteration
如果一个类仅定义__iter__,则__iter__必须返回实现迭代器协议的对象.如果类中的项目包含在内置类型(如列表)中,则__iter___可以简单地返回iter(list).
我想整个概念中都隐含着一个迭代器必须跟踪它在迭代中的位置.
如果希望对象是具有不同迭代序列的迭代器,则可以定义不同的方法来跟踪迭代并前进到下一个项目,然后在obj.next()中使用这些方法.
琐碎的例子:
class Thing(object):
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
def __repr__(self):
return 'Thing({})'.format(self.name)
class Some(object):
def __init__(self):
self.data = None
# need something to keep track of the iteration sequence
self.__index = None
# type of iteration do you want to do
self.direction = self.forward
def __iter__(self):
# reset the iteration
self.__index = None
return self
def next(self):
try:
return self.direction()
except IndexError:
raise StopIteration
def forward(self):
if self.__index is None:
self.__index = -1
self.__index += 1
return self.data[self.__index]
def reverse(self):
if self.__index is None:
self.__index = 0
self.__index -= 1
return self.data[self.__index]
用法
>>> some = Some()
>>> some.data = [Thing('A'),Thing('B'),Thing('C'),Thing('D')]
>>> for thing in some:
print thing,
A B C D
>>> some.direction = some.reverse
>>> for thing in some:
print thing,
D C B A
>>>
因此,也许只需保持下一个简单,然后将树遍历逻辑放在不同的方法中即可.这可能使测试该逻辑更加容易.而且您随时可以添加不同的行为:
def odd_then_even(self):
if self.__index is None:
self.__index = -1
self.__odd = True
self.__index += 2
try:
return self.data[self.__index]
except IndexError:
if not self.__odd:
raise IndexError
self.__odd = False
self.__index = 0
return self.data[self.__index]
>>> some.direction = some.odd_then_even
>>> for thing in some:
print thing,
B D A C
>>>
我很难理解您的内部类解决方案将如何工作,但看起来不对劲的是,迭代器对象的next方法正在返回self,并且似乎next应该返回sequence / collection中的下一项.当您迭代事物的集合时,迭代应该服务于单个事物,而不是迭代器对象的修改后的实例.
内容总结
以上是互联网集市为您收集整理的python-对next()和__iter __()的确切工作方式感到困惑全部内容,希望文章能够帮你解决python-对next()和__iter __()的确切工作方式感到困惑所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。