如何对collections.Iterator进行子类化?

4 投票
2 回答
7927 浏览
提问于 2025-04-16 04:06

根据关于抽象基类(ABCs)的文档,我只需要添加一个next方法,就可以继承collections.Iterator这个类。所以,我使用了以下这个类:

class DummyClass(collections.Iterator):
    def next(self):
        return 1

但是,当我尝试创建这个类的实例时,出现了错误:

>>> x = DummyClass()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class DummyClass with abstract methods __next__

我在想我是不是做了什么傻事,但就是搞不清楚问题出在哪。有没有人能帮我解答一下?我可以添加一个__next__方法,但我原以为这个方法只是针对C语言的类。

2 个回答

3

要让一个对象可以被循环使用,并不一定非得从Iterator类继承。不过在我的情况下,这是必须的,所以我这样做了:

from collections.abc import Iterator

class MyIterator(Iterator):

    def __init__(self, items, property1, property2):
        self.items = items
        self.property1 = property1
        self.property2 = property2
    
    def __iter__(self):
        return self.items.__iter__()

    def __next__(self):
        return self.items.__next__()

测试代码是:

my_iterator = MyIterator([1, 2, 3], "value 1", 2)

for item in my_iterator:
    print(f'{item} ', end='')
print()
print(my_iterator.property1)
print(my_iterator.property2)

输出结果是:

1 2 3
value 1
2

相关文档在这里:collections.abc.Iterator

10

看起来你在使用Python 3.x,而你的代码在Python 2.x上运行得很好。

>>> import collections
>>> class DummyClass(collections.Iterator):
...     def next(self):
...         return 1
... 
>>> x = DummyClass()
>>> zip(x, [1,2,3,4])
[(1, 1), (1, 2), (1, 3), (1, 4)]

但是在Python 3.x中,你应该实现 __next__ 而不是 next,具体可以参考这个Python 3的文档。(记得查看正确的版本哦!)

>>> import collections
>>> class DummyClass(collections.Iterator):
...     def next(self):
...         return 1
... 
>>> x = DummyClass()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can’t instantiate abstract class DummyClass with abstract methods __next__
>>> class DummyClass3k(collections.Iterator):
...     def __next__(self):
...         return 2
... 
>>> y = DummyClass3k()
>>> list(zip(y, [1,2,3,4]))
[(2, 1), (2, 2), (2, 3), (2, 4)]

这个变化是由PEP-3114 — 将 iterator.next() 重命名为 iterator.__next__()引入的。

撰写回答