Python 在创建实例后覆盖

Python 在创建实例后覆盖,python,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):

我正在玩弄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
我有一个
表单
,它有一个元类
FormMetaClass
。 为了有一个替代构造函数,我使用了
@classmethod
。 我创建了一个
实例
,到目前为止它似乎还可以工作

不起作用的是交替调用
\uuuu repr\uuuu
(或
\uuu str\uuuu
)。 当我通过
MyForm()
创建实例时,一切都很好。 当我通过
@classmethod
创建实例时,会采用一些“默认”实现

我期待托马斯·克鲁克,但我得到了


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

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

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

>>> form is MyForm
True
>>> print(MyForm)
<class '__main__.MyForm'>
或者,作为一种完整的方法:

@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

大概
field.String()
field.Integer()
对象是
FieldDescriptor
实例?我想看看我是否可以重现你的问题,但这不是一个缺少这些对象的问题。添加了描述符。我已经能够重现它,没有描述符。今后,请尝试将你的示例减少到最小的示例;您的问题实际上与元类或描述符没有任何关系,您可以删除这些元类或描述符并仍然观察到相同的行为。是的。愚蠢的我。非常感谢你!
>>> isinstance(form, MyForm)
True
>>> print(form)
Thomas Junk