在实例创建后覆盖

2024-03-28 09:20:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在玩一点Python元编程。你知道吗

class FormMetaClass(type):

    def __new__(cls, clsname, bases, methods):
        # Attach attribute names to the descriptors
        for key, value in methods.items():
            if isinstance(value, FieldDescriptor):
                value.name = key
        return type.__new__(cls, clsname, bases, methods)


class Form(metaclass=FormMetaClass):

    @classmethod
    def from_json(cls, incoming):
        instance = cls()
        data = json.loads(incoming)
        for k, v in data.items():
            if (not hasattr(instance, k)):
                raise KeyError("Atrribute not found")
            instance.__setattr__(k, v)
        return cls

class MyForm(Form):

    first_name = String()
    last_name = String()
    age = Integer()

    def __repr__(self):
        return "{} {}".format(self.first_name, self.last_name)


def main():
    data = json.dumps({'first_name': 'Thomas',
                       'last_name': 'Junk'})
    form = MyForm.from_json(data)
    print(form)

if __name__ == "__main__":
    main()

class FieldDescriptor:

    def __init__(self, name=None, **opts):
        self.name = name
        for key, value in opts.items():
            setattr(self, key, value)

    def __set__(self, instance, value):
        instance.__dict__[self.name] = value


class Typechecked(FieldDescriptor):
    expected_type = type(None)

    def __set__(self, instance, value):
        if not isinstance(value, self.expected_type):
            raise TypeError('expected ' + str(self.expected_type))
        super().__set__(instance, value)


class Integer(Typechecked):
    expected_type = int


class String(Typechecked):
    expected_type = str

我有一个Form,它有一个元类FormMetaClass。 为了有一个替代的构造函数,我使用了@classmethod。 我创建了一个instance,到目前为止似乎还有效。你知道吗

不起作用的是互换地调用__repr__(或__str__)。 当我通过MyForm()创建一个实例时,一切都很好。 当我通过@classmethod创建实例时,会采用一些“默认”实现。你知道吗

我期望Thomas Junk,但我得到了<class '__main__.MyForm'>

你能给我一个提示吗,我忽略了什么?你知道吗


Tags: instancekeynameselfjsondataifvalue
1条回答
网友
1楼 · 发布于 2024-03-28 09:20:27

返回的是类,而不是新创建的实例:

return cls

因此返回MyForm,而不是新实例MyForm(),您只需设置所有属性。您确实看到了类的repr()输出:

>>> form is MyForm
True
>>> print(MyForm)
<class '__main__.MyForm'>

修复很简单,返回instance

return instance

或者,作为一个完整的方法:

@classmethod
def from_json(cls, incoming):
    instance = cls()
    data = json.loads(incoming)
    for k, v in data.items():
        if (not hasattr(instance, k)):
            raise KeyError("Atrribute not found")
        instance.__setattr__(k, v)
    return instance

此时,该方法返回一个实例,一切正常:

>>> isinstance(form, MyForm)
True
>>> print(form)
Thomas Junk

相关问题 更多 >