Python中的递增迭代器(iter)

Incrementing iterator (iter) in Python

本文关键字:iter 迭代器 Python      更新时间:2023-10-16

例如,我有以下字符串:

s = "string"

我正在尝试维护这个字符串对象的迭代器。

it = iter(s)

我知道我可以使用循环并使用next调用来增加it

for i in range(0, len(s)):
    print(next(it))

这将打印该字符串中的所有字符。

但我有几件事想让迭代器做,就像我在std::list上使用C++迭代器一样。

1.)返回迭代器当前指向的元素。

   // In C++, I would do,
   std::string str = "string";
   std::string::iterator it = str.begin();
   *it; // gets the value of element

2.)要获得元素的索引,迭代器位于。

这样我就可以使用Python切片方法获得子字符串:

例如:

s = "string"
s[0:iter_index_in_integer]

在C++中,我可以使用迭代器:

   std::string str = "string";
   std::string::iterator it = str.begin();
   std::string(it, it+3);

有可能像那样在Python中增加迭代器吗?如果不是,那么我可以使用迭代器当前指向的元素的索引,我将如何做到这一点?

Python的内置不提供任何允许您获取迭代器的"当前元素"的内容。迭代器必须支持的仅操作是next,以获得以下元素推进迭代。

然而,编写自己的迭代器来实现其他操作非常简单:

class AugmentedIterator(object):
    _sentinel = object()
    def __init__(self, iterator):
        self.iterator = iterator
        self.value = self._sentinel
    def __iter__(self):
        return self
    def __next__(self):
        if self.value is not self._sentinel:
            self.value, val = self._sentinel, self.value
            return val
        return next(self.iterator)
    def peek(self, default=_sentinel):
        if self.value is not self._sentinel:
            return self.value
        try:
            self.value = next(self.iterator)
        except StopIteration:
            if default is not self._sentinel:
                return default
            raise
        else:
            return self.value

现在,给定任何迭代器it,您可以将其封装到AugmentedIterator中,并且可以随时调用peek()来检查当前元素。

注意,没有end()这样的东西,因为迭代器很容易是无限的。知道迭代器是否没有更多元素的唯一方法是调用next并查看它是否引发StopIteration

对于第二个请求,您可以使用itertools.islice来获取迭代器的切片。但是请注意,islice执行python切片,这允许越界索引:

In [19]: list(islice('string', 0, 1000))
Out[19]: ['s', 't', 'r', 'i', 'n', 'g']

这里是索引1000,因为它比字符串长度大,所以它的意思是:直到结束。这与切片一致:

In [20]: 'string'[:1000]
Out[20]: 'string'

在C++中,如果字符串长度为6,则在尝试使用it+1000时会出现错误。(不是100%确定,但由于指针是可迭代的,至少在某些情况下,你肯定会遇到一些麻烦)。


一般来说,itertools包包含许多有用的功能(在文档的末尾有一些使用它们的配方)。Python还提供了一些与迭代器相关的函数,例如:

  • enumerate:对元素进行迭代,得到相对索引
  • map/filter/reduce
  • iter(callable, sentinel):允许您在给定一个没有参数的函数时获得迭代器:

    for chunk in iter(lambda: file_object.read(4096), ''):
        handle(chunk)
    

    相当于:

    while True:
        chunk = file_object.read(4096)
        if chunk == '':
            break
        handle(chunk)
    

您可以使用内置的enumerate()函数:

for index, element in enumerate(mystring):
    print index
    print element

您可以执行以下操作:

import itertools
s = "mystring"
s2 = ''.join(itertools.islice(s, 0, 3))

但实际上,与其试图直接翻译C++习语,你应该找到Python的方式来做任何你想做的事情,这可能最终会更简洁。