我想编写一个可以扩展最终父类属性而不是替换它的Mixin。例如:
class Base(object):
my_attr = ['foo', 'bar']
class MyMixin(object):
my_attr = ['baz']
class MyClass(MyMixin, Base):
pass
print(MyClass.my_attr)
['巴兹']
如何将MyMixin
写为MyClass.my_attr
并将['foo', 'bar', 'baz']
作为值?
答案可以是MyClass
中的合并,但我想知道是否可以在 MyMixin 中进行合并。与MetaClass或其他东西一样?
答案 0 :(得分:2)
如果你真的想用mixin在类属性上执行此操作,那么你必须使用自定义元类并将Base
之后的mixin放入mro中(这意味着它赢得了#t覆盖基类中的任何内容,只需添加到其中):
class Base(object):
my_attr = ['foo', 'bar']
class MyMixinBase(type):
def __init__(cls, name, parents, attribs):
my_attr = getattr(cls, "my_attr", None)
if my_attr is None:
cls.my_attr = ["baz"]
elif "baz" not in my_attr:
my_attr.append("baz")
class MyMixin(object):
__metaclass__ = MyMixinBase
class MyClass(Base, MyMixin):
pass
print(MyClass.my_attr)
这使得代码非常复杂......此时,仅使用MyMixinBase
作为MyClass
的元类将产生相同的结果:
class MyOtherClass(Base):
__metaclass__ = MyMixinBase
print(MyOtherClass.my_attr)
对于这样的用例,类装饰器工作得很好:
def with_baz(cls):
my_attr = getattr(cls, "my_attr", None)
if my_attr is None:
cls.my_attr = ["baz"]
elif "baz" not in my_attr:
my_attr.append("baz")
return cls
@with_baz
class AnotherClass(Base):
pass
print(AnotherClass.my_attr)
答案 1 :(得分:0)
delete
['baz','foo','bar']
您必须手动合并它们。
答案 2 :(得分:0)
您不能这样做,因为您的第二堂课无法访问第一堂课。一种方法是从每个类中获取null
my_attr
并将它们添加到一起。如果您因任何原因不想这样做,您可以访问所有基地的my_calss
并链接它们:
my_attr