动态添加基类?

2 投票
5 回答
1946 浏览
提问于 2025-04-16 00:45

假设我有一个基础类,定义如下:

class Form(object):
    class Meta:
        model = None
        method = 'POST'

现在有个开发者来了,定义了他的子类,如下:

class SubForm(Form):
    class Meta:
        model = 'User'

结果突然间,method这个属性就消失了。我该怎么“找回来”,而不强迫用户让他的元类继承我的元类呢?我能不能在初始化时,或者在元类的__new__函数中,动态地给Form.Meta添加一个基础类?

5 个回答

1

也许你可以用这样的元类:

class _Meta:
    model = None
    method = "Post"

class MetaForm(type):

    def __init__(cls, name, bases, dct):
        super(MetaForm, cls).__init__(name, bases, dct)
        if hasattr(cls, 'Meta'):            
            meta = getattr(cls, 'Meta')                
            for k,v in _Meta.__dict__.items():
                check = meta.__dict__.get(k)
                if not check:
                    meta.__dict__[k] = v    
        else:
            setattr(cls, "Meta", _Meta)        


class Form(object):
    __metaclass__ = MetaForm

class SubForm(Form):
    class Meta:
        model = 'User'

class Sub2Form(Form):
    pass

sub_form = SubForm()        
sub2_form = Sub2Form()    

print sub_form.Meta.method # prints "Post"
print sub2_form.Meta.model # prints None

这段代码其实很简单,你可能需要根据自己的需求稍作调整。

4

你真的需要把Meta定义成那样吗?如果你只是想通过 form.Meta.method 来访问它,那为什么不直接用一个点字典(dotdict)呢?

class dotdict(dict):
    def __getattr__(self, attr):
        return self.get(attr, None)
    __setattr__= dict.__setitem__
    __delattr__= dict.__delitem__

这样你就可以这么做:

class Form(object):
    def __init__(self):
        self.Meta = dotdict()
        self.Meta.model = None
        self.Meta.method = 'POST'

class SubForm(Form):
    def __init__(self):
        Form.__init__(self)
        self.Meta.model = 'User'
9

只要它们不会覆盖你的 __init__ 方法,或者这个方法会被调用(比如通过 super),你就可以对 Meta 这个内部类进行修改:

class Form(object):
    class Meta:
        model = None
        method = "POST"

    def __init__(self, *args, **kwargs):
        if self.__class__ != Form:
            self.Meta.__bases__ += (Form.Meta,)
        # other __init__ code here.

class SubForm(Form):
    class Meta:
        model = 'User'

撰写回答