代码之家  ›  专栏  ›  技术社区  ›  Sushovan Mandal

Python 3:如何为派生类编写一个\uu iter\uuuuu方法,以便它扩展基类“\uu iter\uuuuu方法”的行为

  •  6
  • Sushovan Mandal  · 技术社区  · 7 年前

    假设我有一个基类:

    class Base:
        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):
            yield 'd', self.D
    

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

    然后我尝试从派生类重写方法调用基类方法,就像我们在 __init__() 功能:

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

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

    class Data(Base):
        D = ''
    
        def __iter__(self):
            yield 'a', self.A
            yield 'b', self.B
            yield 'c', self.C
            yield 'd', self.D
    
    2 回复  |  直到 7 年前
        1
  •  6
  •   Sushovan Mandal    7 年前

    这行不通,因为 super().__iter__() 是生成器,在此上下文中调用生成器没有意义。您要做的是迭代该生成器返回的内容,并从 __iter__ 在里面 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
    
        2
  •  2
  •   juanpa.arrivillaga    7 年前

    必须委托给基类:

    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