Python如何通过多重继承传递__init__参数 [英] How does Python pass __init__ parameters with multiple inheritance

查看:527
本文介绍了Python如何通过多重继承传递__init__参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码,显示了经典的菱形图案:

I have this code, showing a classic diamond pattern:

class A:
    def __init__( self, x ):
        print( "A:" + x )


class B( A ):
    def __init__( self, x ):
        print( "B:" + x )
        super().__init__( "b" )


class C( A ):
    def __init__( self, x ):
        print( "C:" + x )
        super().__init__( "c" )


class D( B, C ):
    def __init__( self ):
        super().__init__( "d" )


d = D()

输出为:

B:d
C:b
A:c

  • B:d很有意义,因为D源自B.
  • 我几乎得到了A:c,尽管我同样可以看到A:b.
  • 但是,C:b位没有任何意义:C不是从B派生的.
    • B:d makes sense, since D derives from B.
    • The A:c I almost get, though I could equally see A:b.
    • However, the C:b bit doesn't make sense: C does not derive from B.
    • 有人可以解释吗?

      不幸的是,诸如之类的问题没有提及参数.

      Questions such as this unfortunately do not mention the parameters.

      推荐答案

      Python中的类是动态组合的-包括继承.

      Classes in Python are dynamically composed - that includes inheritance.

      C:b输出并不意味着B神奇地继承自C.如果您实例化BC,则彼此都不知道.

      The C:b output does not imply that B magically inherits from C. If you instantiate either B or C, none knows about the other.

      >>> B('root')
      B:root
      A:b
      

      但是,D 知道BC:

      class D(B,C):
          ...
      

      有很多技术.但是,其工作原理基本上由两部分组成:

      There is a lot of technicalities available on this. However, there are basically two parts in how this works:

      1. 直接基类按顺序显示.
        • BC之前.
      1. Direct Base Classes are resolved in order they appear.
        • B comes before C.
      • BC的基类必须都遵循.
      • A Base Class of both B and C must follow both.

      对于类D,这意味着基类解析为B->C->AC潜入了BA之间-但仅适用于类D,而不适用于类B.

      For the class D, that means the base classes resolve as B->C->A! C has sneaked in between B and A - but only for class D, not for class B.

      请注意,实际上还涉及另一个 类:默认情况下,所有类均源自object.

      Note that there is actually another class involved: all classes derive from object by default.

      >>> D.__mro__
      (__main__.D, __main__.B, __main__.C, __main__.A, object)
      

      您已经写了A,知道没有任何依据可以接受其参数.但是,BC都不能假定这一点.他们都希望从A对象派生.子类化确实暗示BC也是有效的A对象,但是!

      You have already written A knowing that there is no base to take its parameters. However, neither B nor C can assume this. They both expect to derive from an A object. Subclassing does imply that both B and C are valid A-objects as well, though!

      B CB C之前均有效 A的子类. B->C->A->object不会破坏B期望其超类为A类型.

      It is valid for both B and C to precede B and C, since the two are subclasses of A. B->C->A->object does not break that B expects its super class to be of type A.

      对于所有其他组合,最后以C在任何内容之前(无效)或object在某些内容之前(无效)结束.排除了深度优先分辨率B->A->object->C并复制了B->A->object->C->A->object.

      With all other combinations, one ends up with C preceding nothing (invalid) or object preceding something (invalid). That rules out depth-first resolution B->A->object->C and duplicates B->A->object->C->A->object.

      此方法解析顺序对于启用 mixins :依赖其他类来定义方法解析方式的类很实用.

      This method resolution order is practical to enable mixins: classes that rely on other classes to define how methods are resolved.

      很好的例子字典访问记录器可以接受dictOrderedDict.

      There is a nice example of how a logger for dictionary access can accept both dict and OrderedDict.

      # basic Logger working on ``dict``
      class LoggingDict(dict):
          def __setitem__(self, key, value):
              logging.info('Settingto %r' % (key, value))
              super().__setitem__(key, value)
      
      # mixin of different ``dict`` subclass
      class LoggingOD(LoggingDict, collections.OrderedDict):
          pass
      

      这篇关于Python如何通过多重继承传递__init__参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆