簡體   English   中英

python:模擬class變量的多個inheritance

[英]python: simulating the multiple inheritance of class variables

我有一個 class 層次結構,其中一些方法使用在 class 級別定義的屬性列表。

假設對於 class A我有AX = [propA1, propA2]和子類C我需要C.X = [propA1, propA2, propC] 子類從父類繼承屬性,因此使用super()調用編寫 class 方法是有意義的,每個方法都使用自己的 class 的屬性。

但是,它有點麻煩。 我可以在基礎 class 中以單一方法處理所有屬性。 因此,定義一個包含每個子類的新屬性數組的 class 變量並在cls.__mro__下手動 go 以檢索所有屬性確實感覺更自然。

我想出的(下)似乎相對透明,但它是慣用的嗎? 是否有更典型的編碼模式? 有沒有辦法避免裝飾所有子類?

class Base(object):
    pass

class InheritClassVariable:
    def __init__(self, var, base):
        self.var = var
        self.base = base
    def __call__(self, cls):
        name = self.var
        uname = '_' + name
        bases = [B for B in cls.__mro__ if issubclass(B, self.base)]
        setattr(cls, uname, getattr(cls, name, []))
        value = [item for B in bases for item in getattr(B, uname, [])]
        setattr(cls, name, value)
        return cls

@InheritClassVariable('X', Base)
class A(Base):
    X = ['propA1', 'propA2']

@InheritClassVariable('X', Base)
class B(Base):
    X = ['propB']

@InheritClassVariable('X', Base)
class C(A):
    X = ['propC']

@InheritClassVariable('X', Base)
class D(C,B,A):
    X = ['propD']

if __name__ == "__main__":
    print(f"D.X = {D.X}")

一位評論員提到了元類,這是我不知道的。 我查了一下,發現有一個__init_subclass__方法是為了避免元類的一些使用。

眾所周知,我可以將代碼簡化為(已編輯):

def InheritConstantArray(varname, value=[]):
    """Return a class making the 'varname' array to be inherited in subclasses"""
    basename = f"InheritConstantArray{varname}"

    def init_subclass(cls):

        # it seems __class__ won't work here.  I still don't understand
        # why.  All I know is eval() is dirty so I do a lookup.
        allbases = cls.mro()
        base = [b for b in allbases if b.__name__ == basename][0]

        # collaborate with other classes using __init_subclass__().
        # if we want sevaral variables to be inherited.
        super(base, cls).__init_subclass__()

        # base._X[cls] will store original cls.X
        uvarname = f'_{varname}' if varname[0] != '_' else f'{varname}_'
        if not hasattr(base, uvarname):
            setattr(base, uvarname,  {base: value})
        stored_values = getattr(base, uvarname)
        stored_values[cls] = cls.__dict__.get(varname, [])

        # Then we set cls.X value from base classes
        bases = [b for b in allbases if issubclass(b, base)]
        values = [i for b in bases for i in stored_values.get(b, [])]
        print(cls, base)
        setattr(cls, varname, values)

    dct = {varname: value, '__init_subclass__': init_subclass}
    base = type(basename, (object,), dct)

    return base

class A(InheritConstantArray('X')):
    X = ['A']

class B(A):
    X = ['B']

class C(A):
    X = ['C']

class D(B,C,InheritConstantArray('Y')):
    X = ['D']
    Y = ['d']

class E(D):
    X = ['E']
    Y = ['e']

class F(D):
    X = ['F']
    Y = ['f']

class G(E,F):
    X = ['G']
    Y = ['g']

if __name__ == "__main__":
    print(f"A.X = {A.X}")
    print(f"B.X = {B.X}")
    print(f"C.X = {C.X}")
    print(f"D.X = {D.X} {D.Y}")
    print(f"E.X = {E.X} {E.Y}")
    print(f"F.X = {F.X} {F.Y}")
    print(f"G.X = {G.X} {G.Y}")


不過,我仍然不確定這是否是標准方法。 (是的,在我的實際問題中具有 class 變量和多個 inheritance 有一個非常充分的理由。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM