如何对两个父类的内部类进行子类化,以便在子类上正确定义内部类?

2024-09-30 12:27:55 发布

您现在位置:Python中文网/ 问答频道 /正文

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

我也试过很多次用一种更平易近人的方式来写这个问题,所以如果这有点牵强附会,我道歉

希望这个例子能澄清一些问题:

(对于这个问题,假设我们不知道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

Tags: 方法ininput定义层次结构ipython方式情况
2条回答

好了,伙计们,从g.d.d.c的部分答案来看,我认为我们这里有一个解决方案,它可以干净而简单地适用于任意的类层次结构

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

再次感谢g.d.d.c把我踢向正确的方向

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'>]

您可以使用这样一个事实,即如果A.inner是一个类,并且BC没有显式地对内部类进行子类化,那么B.innerC.inner是同一个对象->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

我们正在利用字典来确保唯一性顺序(如果您使用的版本还不能保证dict顺序,请使用collections.OrderedDict或其他一些顺序集实现)。我们可以确定需要在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,不管哪个类(如果有的话)子类A.innerD.inner工作

相关问题 更多 >

    热门问题