簡體   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