繁体   English   中英

如何子类化两个父类的内部类以在子类 class 上正确定义内部 class?

[英]How do I subclass two parent classes' inner classes to correctly define an inner class on a child class?

我试图在类的层次结构中定义一个内部 class,但我无法找出正确的方法来确保内部 class 正确地子类化父类的相应内部类,而不会在一个或多个的情况下抛出异常的直接父类本身并没有子类化内部 class。

我也试过很多次把这个问题写得比较平易近人,所以如果有点令人头疼,我深表歉意!

希望这个例子能澄清一些事情:

(对于这个问题,假设我们不知道 B 或 C 中的哪一个(如果有的话)定义了 A.Inner 的子类——显然在这个例子中两者都不知道,但这不是重点。)

干杯。

class A:
    class Inner:
        ...
class B(A):
    ...
class C(A):
    ...
class D(B, C):
    class Inner(B.Inner, C.Inner):
        ...
>>>
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-163-6f592c573c6f> in <module>
      6 class C(A):
      7     ...
----> 8 class D(B, C):
      9     class Inner(B.Inner, C.Inner):
     10         ...

<ipython-input-163-6f592c573c6f> in D()
      7     ...
      8 class D(B, C):
----> 9     class Inner(B.Inner, C.Inner):
     10         ...

TypeError: duplicate base class Inner

您可以使用这样一个事实,即如果A.inner是 class,并且BC没有显式地子类化内部 class,那么B.innerC.inner相同的 object -> A.inner

>>> class A:
...  class inner: pass
... 
>>> class B(A): pass
... 
>>> class C(A): pass
... 
>>> B.inner is C.inner
True
>>> C.inner is A.inner
True

我们利用字典来确保唯一性顺序(使用collections.OrderedDict或其他一些 ordered_set 实现,如果您使用的版本尚不能保证字典顺序)。 我们可以像这样确定我们需要在D.inner上子类化哪些类:

inner_classes = {getattr(klass, 'inner'): True for klass in [C, B]  # control your MRO here.
                 if getattr(klass, 'inner') is not A.inner}
# Ensure that we also extend A.inner, in case neither B nor C subclasses A.inner
inner_classes[A.inner] = True
class D(A):
  class inner(*inner_classes.keys()): pass

通过这种方式,我们可以获得一致的 MRO,哪个 class(如果有的话)子类A.innerD.inner工作并不重要。

好的伙计们,从 gddc 的部分回答开始,我认为我们这里有一个解决方案,它可以干净简单地用于任意 class 层次结构。

我将对它进行几天的测试,看看它是否能正常工作。 我仍然对手动指定基数的要求不满意——我觉得包装器内部的某种内省可以自动处理这个问题。 请提出更多建议。

再次感谢 gddc 将我踢向正确的方向!

def inner_class(*bases):
    def _inner_class(cls):
        bs = []
        for b in bases:
            try: bs.append(getattr(b, cls.__name__))
            except AttributeError: pass
        bs = sorted(set(bs), key = bs.index)
        return type(cls)(
            cls.__name__,
            (cls, *bs),
            {}
            )
    return _inner_class

class A:
    class Inner:
        ...
class B(A):
    class Inner(A.Inner):
        ...
class C(A):
    ...
class D(A):
    ...
class E(B, C, D):
    @inner_class(B, C, D)
    class Inner:
        ...

print(E.Inner.mro())

>>> [<class '__main__.Inner'>, <class '__main__.E.Inner'>, <class '__main__.B.Inner'>, <class '__main__.A.Inner'>, <class 'object'>]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM