gpt4 book ai didi

python:模拟类变量的多重继承

转载 作者:行者123 更新时间:2023-12-03 16:59:28 25 4
gpt4 key购买 nike

我有一个类层次结构,其中一些方法使用在类级别定义的属性列表。
假设对于类(class) A我有 A.X = [propA1, propA2]和子类 C我需要C.X = [propA1, propA2, propC] .子类从父类继承属性,因此使用 super() 编写类方法是有意义的。调用,每个调用都使用自己类的属性。
然而,这有点麻烦。我可以在基类中的单个方法中处理所有属性。因此,为每个子类定义一个包含一组新属性的类变量,然后手动向下搜索 cls.__mro__ 确实感觉更自然。检索所有属性。
我想出的(下面)似乎相对透明地工作,但它是惯用的吗?是否有更典型的编码模式?有没有办法避免装饰所有子类?

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}")


不过,我仍然不确定这是否是标准的做法。 (是的,在我的实际问题中使用类变量和多重继承是有充分理由的。)

关于python:模拟类变量的多重继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63022449/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com