2

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

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

现在一个开发人员来了很长一段时间,并定义了他的子类,如:

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

现在突然method失去了属性。我怎样才能“取回”而不强迫用户从我的继承他的元类?我可以Form.Meta在初始化程序或元类的__new__函数中动态添加基类吗?

4

5 回答 5

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'
于 2010-07-13T08:44:51.807 回答
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'
于 2010-07-14T18:13:30.613 回答
1

您可以检查__init__父对象的方法中的方法属性,并在需要时对其进行更新。当然,只有当你保护代码的程序员在他的构造函数中调用它时,这才会起作用。

class Form(object):
    def __init__(self):
            if not getattr(self.Meta,'method',False):
                    self.Meta.method='POST'
    class Meta:
       model = None
       method = 'POST'

class SubForm(Form):
    class Meta:
       model = 'User'
于 2010-07-12T08:39:41.520 回答
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

代码非常简单,也许您需要根据自己的需要来调整它。

于 2010-07-15T17:19:12.587 回答
0

也许我可以省略Meta里面的默认类Form并使用默认字典来代替?

meta_defaults = {'model':None, 'method':'POST'}
meta_vars = meta_defaults
meta_vars.update(Form.Meta.__dict__)
于 2010-07-06T04:07:50.543 回答