python - 如何实现自定义迭代器以便可以嵌套它们?

标签 python nested iterator

我只是在查找一些有关 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/

相关文章:

python - PuLP CBC 多线程不适用于 COIN_CMD

Python在DNA序列中找到最长的ORF

python - 在 Python 中退出 Tks 主循环?

c++ - 如何使用 json11 库在 json 中添加子/嵌套元素?

C++ 带括号的取消引用(带迭代器)

c++ - 基于范围的对 <Iterator,Iterator>

c++ - 如何在 C 风格数组上使用 find_if 和 reverse_iterator?

python - 对于在 python 中使用 `with` 关键字的类,我可以让它 __repr__ (打印)本身吗?

javascript - 如何访问和处理嵌套对象,数组或JSON?

java - 嵌套 while 循环在第一次迭代后停止?