Python 3:如何为派生 class 编写 __iter__ 方法,以便它扩展基本 class' __iter__ 方法的行为

Python 3: How to write a __iter__ method for derived class so that it extends on the behaviour of the base class' __iter__ method

假设我有一个基地 class:

class Base:
    A = False
    B = ''
    C = ''

    def __iter__(self):
        yield 'a', self.A
        yield 'b', self.B
        yield 'c', self.C

然后是从这个基派生的 class:

class Data(Base):
    D = ''

    def __iter__(self):
        yield 'd', self.D

当数据实例 class 转换为 dict 类型时,这当然只在 dict( Data() ) 上创建一个包含 { 'd': <value> } 的字典;因为据我所知,派生的 class __iter__ 方法有效地覆盖了基础 class __iter__ 方法。

然后我尝试从派生的 class 重写方法调用基础 class 方法,就像我们在 __init__() 函数中所做的那样:

def __iter__(self):
    super().__iter__()
    yield 'd', self.D

但是 IDE 将其标记为错误。为什么这不起作用? 以及如何定义派生的 iter 方法来扩展已经存在的基础 class iter 方法,以便我只需要为派生的 class 中添加的变量添加 yield?在派生的 class iter 方法中再次手动写出所有产量,这是目前我实现它的唯一解决方案?为什么?

class Data(Base):
    D = ''

    def __iter__(self):
        yield 'a', self.A
        yield 'b', self.B
        yield 'c', self.C
        yield 'd', self.D

您必须委托给基地 class:

In [1]: class Base:
   ...:     A = False
   ...:     B = ''
   ...:     C = ''
   ...:
   ...:     def __iter__(self):
   ...:         yield 'a', self.A
   ...:         yield 'b', self.B
   ...:         yield 'c', self.C
   ...:

In [2]: class Data(Base):
   ...:     D = ''
   ...:
   ...:     def __iter__(self):
   ...:         yield from super().__iter__()
   ...:         yield 'd', self.D
   ...:

In [3]: print(list(Data()))
[('a', False), ('b', ''), ('c', ''), ('d', '')]

In [4]: print(dict(Data()))
{'c': '', 'b': '', 'd': '', 'a': False}

Python 3 允许使用 yield from 语法,在 Python 2 中使用:

class Base(object): # make sure to inherit from object for super to work
    A = False
    B = ''
    C = ''

    def __iter__(self):
        yield 'a', self.A
        yield 'b', self.B
        yield 'c', self.C

class Data(Base):
    D = ''

    def __iter__(self):
        for x in super(Data, self).__iter__():
            yield x
        yield 'd', self.D

这行不通,因为 super().__iter__() 是一个生成器,在此上下文中调用生成器没有意义。您想要做的是遍历该生成器返回的内容,并从 __iter__ in Data:

中生成它们

Python 2:

def __iter__(self):
    for i in super().__iter__():
        yield i
    yield 'd', self.D

但在 Python 3 中,这可以更简洁地写为:

def __iter__(self):
    yield from super().__iter__()
    yield 'd', self.D