我需要创建一个类,它使用迭代器协议从数据流中一次返回一个字符,但是它也有一个类似于文件对象tell()
的方法,返回什么位置它目前在流中。
基本上,这就是我需要的:
>>> x = MyIterator('abcdefghijklmnopqrstuvwxyz')
>>> x.tell()
0
>>> next(x)
'a'
>>> next(x)
'b'
>>> next(x)
'c'
>>> x.tell()
3
>>> next(x)
'd'
>>> x.tell()
4
最狡猾的方式是什么?我可以用某种方式使用生成器来做,或者我是否必须创建一个实现迭代器协议的类"手动"? (即具有__next__()
方法的类,当数据用完时手动引发StopIteration
请注意,这个问题有点简化了我的实际需求。我实际上需要tell()
- analogue来返回流位置的函数,而不仅仅是位置,所以请不要告诉我"只是让我的迭代器的调用者使用{{1} }"或类似的东西。
答案 0 :(得分:3)
我可以用某种方式使用发生器吗
不是真的。 (理论上你可以通过将计数器存储为生成器函数的函数属性来实现,但是尝试使函数引用自身是一个冒险的命题。)
还是我必须创建一个“手动”实现迭代器协议的类? (即具有
__next__()
方法的类,当数据用完时手动引发StopIteration)
是和否。是的,您必须创建一个迭代器类,但这并不意味着您必须手动提升StopIteration。假设您希望迭代器包装一些可迭代的源,那么您可以依靠该源来引发StopIteration。这是一个简单的例子:
class MyIter(object):
def __init__(self, source):
self.source = iter(source)
self.counter = 0
def next(self):
self.counter += 1
return next(self.source)
def __iter__(self):
return self
def tell(self):
return self.counter
(这使用next
和Python 2;对于Python 3,您必须将def next
更改为def __next__
。)
然后:
>>> x = MyIter('abc')
>>> for item in x:
... print(item, x.tell())
a 1
b 2
c 3
答案 1 :(得分:1)
如果计算它并不太昂贵,请让迭代器同时产生值和位置。或者,提供两种迭代方法,一种只产生值,另一种产生值和位置。