Python自定义迭代器

在这篇文章中,我们将学习什么是迭代器,以及如何在名为__iter____next__ 的类方法的帮助下创建一个自定义迭代器。我们还将学习如何在Python的生成器的帮助下创建一个自定义迭代器。

在Python中借助于类方法__iter____next__ 创建一个自定义迭代器

现在当你说到迭代器时,顾名思义,它将被用来进行迭代。

如果你来自C、C++和Java等语言,我们有一个共同的概念:++ 。当我们谈论迭代的时候,还有一个概念是已知的:for 循环。

比方说,我们有一个包含5个元素的列表。使用一个循环,我们可以从第一个元素迭代到最后一个元素。

这样,我们就有了一个带有一些数值的列表,如果我们想用索引号逐一打印它们。

如果我们传递我们的索引0,它将给我们提供第一个元素,2。如果我们使用索引值1,它将为我们提供第二个元素,5。

Numbers=[2,5,10,3,1]
print(Numbers[0])
print(Numbers[1])

输出:

2
5

另一种打印数值的方法是使用循环。我们可以对一个列表进行迭代并打印所有的值。

Numbers=[2,5,10,3,1]
for i in Numbers:
    print(i)

输出:

2
5
10
3
1

现在我们还有一种方法:通过使用迭代器。一般来说,迭代器在for 循环的背后工作。

我们将使用iter() 函数来理解一个迭代器,它将把我们的列表转换成一个迭代器。这个迭代器不会给我们所有的值,它每次只给一个值。

Numbers=[2,5,10,3,1]
ITR=iter(Numbers)
print(ITR)

我们可以看到它正在打印一个迭代器的对象。

<list_iterator object at 0x000001FEDCFF7310>

但是,如果你想要这个值,你可以设置ITR.__next__() ,这是一个内建的方法。它将在特定对象上第一次调用__next__() 方法时给我们第一个值;这与我们使用索引值的方式相同,但好处是我们不必使用索引值。

umbers=[2,5,10,3,1]
ITR=iter(Numbers)
print(ITR.__next__())

输出:

2

当我们在下一个执行行中执行ITR.__next__() ,它将给出下一个值。在这个场景背后,迭代器将有多个值,所以当我们调用__next__() 方法时,它将拾取一个值。

再说,当我们调用__next__() ,它知道i 的最后一个值,这意味着它将保留最后一个值的状态。这就是迭代器的魅力;当我们再次调用该函数时,它将保留旧值。

我们可以使用一个类来创建我们的迭代器。使用该类,我们可以单独打印前10个值。

为了达到这个目的,我们将有一个名为TopValues 的类,在这个类中,我们将指定一个计数器。

为此,我们将使用__init__ 函数,在这里我们将定义我们的计数器变量self.N=1 ;显然,计数器将从1开始初始化。我们需要两个重要方法来创建我们的自定义迭代器。

第一个是iter() 方法,它将给我们迭代器的对象,然后next() 方法将提供下一个值或对象。在__next__ 方法中,我们没有返回self.N ,而是使用了一个叫做VALUE 的变量,我们将把self.N ,在下一行中,我们把self.N 递增为1。

这样,它将在每一个下一次迭代中被递增,然后返回VALUE ,而不是self.N ,因为self.N 在下一次迭代中被递增。

class TopValues:
    def __init__(self):
        self.N=1
    def __iter__(self):
        return self
    def __next__(self):
        VALUE=self.N
        self.N+=1
        return VALUE

我们的迭代器现在已经准备好了,我们可以创建一个TopValues 类的对象。让我们使用一个循环,因为通常当你有一个迭代器时,我们可以使用循环。

T_Val=TopValues()
for i in T_Val:
    print(i)

现在当我们执行这段代码时,我们会得到成千上万的值。

1
2
3
4
5
....
1000

让我们试着理解发生了什么。为了检查迭代器是否工作,我们将使用__next__()

print(T_Val.__next__())

这一行将打印第一个迭代值,1 ,但循环出了什么问题?问题在于,这个循环将从起点走到终点;我们假设终点是10,但我们没有提到应该在哪里停止。

当我们使用循环时,它将调用next() 函数,这就是它的工作方式。for 循环内部使用next() 函数;因此,它将反复调用这个next() 函数。

我们必须在__next__ 方法里面应用一个条件。

我们还必须设置else 块;在这个块里面,我们将引发一个异常。否则,在打印了10个值之后,循环将打印None

class TopValues:
    def __init__(self):
        self.N=1
    def __iter__(self):
        return self
    def __next__(self):
        if self.N<=10:
            VALUE=self.N
            self.N+=1
            return VALUE
        else:
            raise StopIteration
T_Val=TopValues()
for i in T_Val:
    print(i)

输出:

1
2
3
4
5
6
7
8
9
10

在Python生成器的帮助下创建一个自定义迭代器

现在让我们试着创建一个生成器函数来做同样的事情。生成器要简单得多,因为它为我们处理了__iter__()__next__() 方法。

如果我们试着写一个名为Our_Gen() 的生成器函数,我们将在这个函数中传递参数。

由于我们是在列表上循环,所以我们是一次产生一个项目。而且,当没有更多的项目可以循环时,它会自动处理,并引发一个异常来停止迭代。

现在我们在Our_Gen() 函数上循环,所以它应该一次打印出一个项目。如果我们运行它,我们可以看到我们一次得到一个。

def Our_Gen(n_list):
    for i in n_list:
        yield i
Func=Our_Gen([2,5,10,3,1])
for i in Func:
    print(i)

输出:

2
5
10
3
1

为了确保我们的next() 函数仍然在工作。执行后,我们得到五个元素我们得到一个停止迭代的异常。

def Our_Gen(n_list):
    for i in n_list:
        yield i
Func=Our_Gen([2,5,10,3,1])
print(Func.__next__())
print(Func.__next__())
print(Func.__next__())
print(Func.__next__())
print(Func.__next__())
print(Func.__next__())

输出:

2
5
10
3
1
Traceback (most recent call last):
  File "c:UsersDellDesktopdemodemo.py", line 56, in <module>
    print(Func.__next__())
StopIteration

生成器比类更容易编写。但是根据你的用例,你可能需要知道如何在一个类中做__iter__() 方法和__next__() 方法。

你可以从这里阅读更多关于创建一个自定义迭代器的信息。