Python 3.x 为类创建装饰器以应用dataclass和JsonSchemaMixin…不起作用

Python 3.x 为类创建装饰器以应用dataclass和JsonSchemaMixin…不起作用,python-3.x,python-decorators,python-dataclasses,Python 3.x,Python Decorators,Python Dataclasses,我确实审查了所有现有的SO问题,尽可能在谷歌上搜索,尝试了一些不同的选择,但似乎无法得到我想要的工作 背景 简单的问题-我的代码中有一堆数据类 我希望将它们全部更改为继承自数据类jsonschemaJsonSchemaMixin,以便我可以通过编程方式为它们生成模式。 当然,简单的方法是我可以将代码中的所有实例都更改为从JsonSchemaMixinmixin继承 但我想我也可以编写自己的装饰器,它将a)应用@dataclass,b)一次性混入dataclasses模式。。。我的想法是减少出错的

我确实审查了所有现有的SO问题,尽可能在谷歌上搜索,尝试了一些不同的选择,但似乎无法得到我想要的工作

背景 简单的问题-我的代码中有一堆数据类

我希望将它们全部更改为继承自
数据类jsonschema
JsonSchemaMixin
,以便我可以通过编程方式为它们生成模式。

当然,简单的方法是我可以将代码中的所有实例都更改为从
JsonSchemaMixin
mixin继承

但我想我也可以编写自己的装饰器,它将a)应用@dataclass,b)一次性混入
dataclasses模式
。。。我的想法是减少出错的机会,我可以尝试编写一个类装饰器(我只创建和使用过我自己的函数装饰器)

#旧
@数据类
X类:
....
#在所有地方添加“手动”混合器
@数据类
X类(JsonSchemaMixin):
x:int
y:浮子
#我想让我自己的装饰师做到这两个方面:
@数据类_mixedin
X类:
x:int
y:浮子
问题 非常简单的问题-我无法让它工作:(

我试过的

试试第一个:
从数据类导入数据类
从dataclasses_jsonschema导入JsonSchemaMixin
def dc_模式(cls):
@数据类
装饰类(JsonSchemaMixin,cls):
通过
返回
@dc_模式
类别数据:
x:int
y:浮子
a=数据(x=5,y=1.1)
上述操作失败,出现意外的关键字args x&y

试试第二个:

def dc_方案2(cls):
#尝试直接应用dataclass():
装饰类(JsonSchemaMixin,cls):
通过
_装饰=数据类(_装饰)
返回
@dc_方案2
类别数据2:
x:int
y:浮子
d=数据2(x=1,y=1.1)
再次-此操作因意外参数而失败

所以我猜我缺少了
dataclass
遍历类结构来查找带有注释的类变量()


但我不知道如何做到这一点,一个可能的解决方案是使用元类。 请参见此示例:

从数据类导入数据类,是\u数据类
从dataclasses_jsonschema导入JsonSchemaMixin
类别EntityMeta(类型):
定义(cls、名称、基础、类别):
new_class=super()
返回dataclass()(新的_类)
类BaseEntity(JsonSchemaMixin,元类=EntityMeta):
通过
类SomeClass(基本实体):
id:str
姓名:str
断言是\u数据类(SomeClass)
断言issubclass(SomeClass,JsonSchemaMixin)
x=SomeClass(1,“你好,世界”)
断言x.id==1
断言x.name==“你好,世界”
类SomeOtherClass(基本实体):
foo:str
姓名:str
x=其他类别(“foo”、“ufo”)
断言x.foo==“foo”
断言x.name==“ufo”
打印(SomeOtherClass.json_schema())
我不推荐这个,因为你 无论如何都需要从基类继承,而且代码的详细程度差别很小。这样会丢失有用的特性,例如类型 在提供此类帮助的IDE中使用MyPy(除非编写专用插件)或Pylance进行编码时的提示


我建议您考虑一下:它可能具有您想要的特性。

一个可能的解决方案是使用元类。 请参见此示例:

从数据类导入数据类,是\u数据类
从dataclasses_jsonschema导入JsonSchemaMixin
类别EntityMeta(类型):
定义(cls、名称、基础、类别):
new_class=super()
返回dataclass()(新的_类)
类BaseEntity(JsonSchemaMixin,元类=EntityMeta):
通过
类SomeClass(基本实体):
id:str
姓名:str
断言是\u数据类(SomeClass)
断言issubclass(SomeClass,JsonSchemaMixin)
x=SomeClass(1,“你好,世界”)
断言x.id==1
断言x.name==“你好,世界”
类SomeOtherClass(基本实体):
foo:str
姓名:str
x=其他类别(“foo”、“ufo”)
断言x.foo==“foo”
断言x.name==“ufo”
打印(SomeOtherClass.json_schema())
我不推荐这个,因为你 无论如何都需要从基类继承,而且代码的详细程度差别很小。这样会丢失有用的特性,例如类型 在提供此类帮助的IDE中使用MyPy(除非编写专用插件)或Pylance进行编码时的提示


我建议您考虑一下:它可能具有您想要的功能。

谢谢Roberto!…我将深入研究元类方法。我在任何地方都使用mypy和键入,所以我不想放弃这些,所以我想我会接受您的建议,通过@dataclass和mixin“手动”完成。谢谢Robert哦!…我将深入研究元类方法。我在任何地方都使用mypy和键入,所以我不愿意放弃这些,所以我想我会接受你的建议,通过@dataclass和mixin“手动”完成。