在本文中,我们将了解什么是迭代器以及如何借助 __iter__
和 __next__
类方法创建自定义迭代器。 我们还将学习如何在 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 加一。
这样它将在每次下一次迭代中递增,然后返回 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
现在让我们尝试创建一个执行相同操作的生成器函数。 生成器要简单得多,因为它们为我们处理 __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:\Users\Dell\Desktop\demo\demo.py", line 56, in <module>
print(Func.__next__())
StopIteration
生成器比类更容易编写。 但根据您的用例,您可能需要知道如何在类中执行 __iter__()
方法和 __next__()
方法。