我只是在查找一些有关 python 迭代器的东西,偶然发现了这个 W3School iterator example :
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myclass = MyNumbers()
myiter = iter(myclass)
for x in myiter:
print(x)
代码将 1 到 20 之间的数字打印到控制台。
我想知道该代码是否适用于嵌套迭代器,因为它使用一个属性来跟踪已经通过的迭代次数。 因此,我设置了一个小示例(只有 3 次迭代,而不是 20 次),事实上,它没有按预期工作:
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 3:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myclass = MyNumbers()
myiter = iter(myclass)
for x in myiter:
for y in myiter:
print('outer value: ' + str(x))
print('inner value: ' + str(y))
print("*"*50)
for x in myclass:
for y in myclass:
print('outer value: ' + str(x))
print('inner value: ' + str(y))
print("*"*50)
for x in iter(myclass):
for y in iter(myclass):
print('outer value: ' + str(x))
print('inner value: ' + str(y))
print("*"*50)
输出:
outer value: 1
inner value: 1
outer value: 1
inner value: 2
outer value: 1
inner value: 3
**************************************************
outer value: 1
inner value: 1
outer value: 1
inner value: 2
outer value: 1
inner value: 3
**************************************************
outer value: 1
inner value: 1
outer value: 1
inner value: 2
outer value: 1
inner value: 3
**************************************************
我可以看到这些结果是如何发生的;跟踪迭代次数的属性由内部迭代器增加,该迭代器立即失败 self.a <= 3 check
一旦内部迭代器完成,就用于外部迭代器。
然后我尝试了一个类似的列表示例,它们的行为有所不同:
a = [1, 2, 3]
for x in a:
for y in a:
print('outer value: ' + str(x))
print('inner value: ' + str(y))
print("*"*50)
输出:
outer value: 1
inner value: 1
outer value: 1
inner value: 2
outer value: 1
inner value: 3
**************************************************
outer value: 2
inner value: 1
outer value: 2
inner value: 2
outer value: 2
inner value: 3
**************************************************
outer value: 3
inner value: 1
outer value: 3
inner value: 2
outer value: 3
inner value: 3
**************************************************
此版本的工作原理与嵌套迭代器的预期相同。我现在的问题是:如何重写给定的示例,使其按预期工作?我想过一个生成可迭代对象的工厂,但这似乎非常复杂(而且我不确定它是否会起作用)。有人知道一种简单/更容易的方法吗?
最佳答案
一个快速而肮脏的例子来展示如何实现这一点:
class MyList:
def __init__(self, ls):
self.ls = ls
def __iter__(self):
class MyListIter:
def __init__(self, ls):
self.ls = ls.copy()
self.n = -1
def __next__(self):
self.n += 1
if self.n >= len(self.ls):
raise StopIteration
return self.ls[self.n]
return MyListIter(self.ls)
x = MyList([1, 2, 4, 8])
for i in x:
for j in x:
print(i, j)
输出:
1 1
1 2
1 4
1 8
2 1
2 2
2 4
2 8
4 1
4 2
4 4
4 8
8 1
8 2
8 4
8 8
诀窍是我们需要单独跟踪每个迭代,因此我在这里添加了另一个对象来处理这个问题。
还有一些其他方法可以完成此操作,但这可能是最简单的模式。
关于python - 如何实现自定义迭代器以便可以嵌套它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73950440/