我应该如何创建一个也支持 tell() 方法的迭代器?
How should I create an iterator that also supports a tell() method?
我需要创建一个 class,它 return 使用迭代器协议从数据流中一次一个字符,但它也有一个类似于文件对象的方法 tell()
, return正在查看它当前在流中的位置。
基本上,这就是我需要的:
>>> x = MyIterator('abcdefghijklmnopqrstuvwxyz')
>>> x.tell()
0
>>> next(x)
'a'
>>> next(x)
'b'
>>> next(x)
'c'
>>> x.tell()
3
>>> next(x)
'd'
>>> x.tell()
4
最符合 pythonic 的方法是什么?我能以某种方式使用生成器来实现吗,还是我必须创建一个实现迭代器协议 "by hand" 的 class? (即 class 和 __next__()
方法在数据用完时手动引发 StopIteration
)
请注意,这个问题有点简化了我的实际需求。我实际上需要 tell()
-模拟到 return 流位置的函数,而不仅仅是位置,所以请不要告诉我 "just make the caller of my iterator use enumerate()
" 或类似的东西。
Can I do it using a generator somehow
不是真的。 (理论上你可以通过将计数器存储为生成器函数的函数属性来实现,但试图让函数引用自身是一个冒险的提议。)
or do I have to create a class that implements the iterator protocol "by hand"? (i.e. a class with a __next__()
method that manually raises StopIteration when it runs out of data)
是也不是。是的,您必须创建一个迭代器 class,但这并不意味着您必须手动引发 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
a la 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
如果计算它的成本不是太高,让迭代器产生值和位置。或者,提供两种迭代方法,一种只产生值,另一种产生值和位置。
我需要创建一个 class,它 return 使用迭代器协议从数据流中一次一个字符,但它也有一个类似于文件对象的方法 tell()
, return正在查看它当前在流中的位置。
基本上,这就是我需要的:
>>> x = MyIterator('abcdefghijklmnopqrstuvwxyz')
>>> x.tell()
0
>>> next(x)
'a'
>>> next(x)
'b'
>>> next(x)
'c'
>>> x.tell()
3
>>> next(x)
'd'
>>> x.tell()
4
最符合 pythonic 的方法是什么?我能以某种方式使用生成器来实现吗,还是我必须创建一个实现迭代器协议 "by hand" 的 class? (即 class 和 __next__()
方法在数据用完时手动引发 StopIteration
)
请注意,这个问题有点简化了我的实际需求。我实际上需要 tell()
-模拟到 return 流位置的函数,而不仅仅是位置,所以请不要告诉我 "just make the caller of my iterator use enumerate()
" 或类似的东西。
Can I do it using a generator somehow
不是真的。 (理论上你可以通过将计数器存储为生成器函数的函数属性来实现,但试图让函数引用自身是一个冒险的提议。)
or do I have to create a class that implements the iterator protocol "by hand"? (i.e. a class with a
__next__()
method that manually raises StopIteration when it runs out of data)
是也不是。是的,您必须创建一个迭代器 class,但这并不意味着您必须手动引发 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
a la 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
如果计算它的成本不是太高,让迭代器产生值和位置。或者,提供两种迭代方法,一种只产生值,另一种产生值和位置。