Python 具有多态性的棉花糖树结构
Python marshmallow tree structure with polymorphism
我有以下树结构代码:
class Node:
def __init__(self, node_id: str):
self.node_id = node_id
self.children = []
def add_child(self, node: 'Node'):
if isinstance(node, Node):
self.children.append(node)
class ValueNode(Node):
def __init__(self, value: bool, **kwargs):
Node.__init__(self, **kwargs)
self.value = value
class LogicNode(Node):
def __init__(self, logic_operator: str, **kwargs):
Node.__init__(self, **kwargs)
self.logic_operator = logic_operator
a = Node("a")
b = LogicNode("or", node_id="b")
c = ValueNode(True, node_id="c")
d = ValueNode(False, node_id="d")
b.add_child(c)
b.add_child(d)
a.add_child(b)
如何将对象 a
序列化为 json 并再次序列化为 python 对象,同时保持正确的类型和树结构?
我试过的:
我正在尝试将此树结构序列化为 json,以便通过 API 发送到 ui。我发现了棉花糖,但不幸的是,我不知道该怎么做。我有这个作为模式 atm。
class NodeSchema(Schema):
node_id = fields.String()
children = fields.Nested('self', many=True)
@post_load
def load(self, data):
return Node(**data)
class ValueNodeSchema(NodeSchema):
value = fields.Boolean()
class LogicNodeSchema(NodeSchema):
logic_operator = fields.String()
这里的问题是,当序列化为 json 时,即使子节点是逻辑节点或值节点(有点符合预期),也只有 Node 的属性存在。我发现了 marshmallow-oneofschema here github 但我无法使用它,因为我必须用它替换:
# In NodeSchema
children = fields.Nested('self', many=True)
与:
class SomeNodeSchema(OneOfSchema):
type_schemas = {
'node': NodeSchema,
'logic_node': LogicNodeSchema,
'value_node': ValueNodeSchema,
}
def get_obj_type(self, obj):
if isinstance(obj, LogicNode):
return 'logic_node'
if isinstance(obj, ValueNode):
return 'value_node'
elif isinstance(obj, Node):
return 'node'
# In NodeSchema
children = fields.Nested(SomeNodeSchema, many=True)
但这会导致循环导入,这使得它不可能。
I found about marshmallow-oneofschema
虽然没有集成到核心,但我认为marshmallow-oneofschema是做多态的推荐方式。
this leads to a circular import
您可以将名称作为字符串传递来解决循环导入问题。
children = fields.Nested('SomeNodeSchema', many=True)
我有以下树结构代码:
class Node:
def __init__(self, node_id: str):
self.node_id = node_id
self.children = []
def add_child(self, node: 'Node'):
if isinstance(node, Node):
self.children.append(node)
class ValueNode(Node):
def __init__(self, value: bool, **kwargs):
Node.__init__(self, **kwargs)
self.value = value
class LogicNode(Node):
def __init__(self, logic_operator: str, **kwargs):
Node.__init__(self, **kwargs)
self.logic_operator = logic_operator
a = Node("a")
b = LogicNode("or", node_id="b")
c = ValueNode(True, node_id="c")
d = ValueNode(False, node_id="d")
b.add_child(c)
b.add_child(d)
a.add_child(b)
如何将对象 a
序列化为 json 并再次序列化为 python 对象,同时保持正确的类型和树结构?
我试过的:
我正在尝试将此树结构序列化为 json,以便通过 API 发送到 ui。我发现了棉花糖,但不幸的是,我不知道该怎么做。我有这个作为模式 atm。
class NodeSchema(Schema):
node_id = fields.String()
children = fields.Nested('self', many=True)
@post_load
def load(self, data):
return Node(**data)
class ValueNodeSchema(NodeSchema):
value = fields.Boolean()
class LogicNodeSchema(NodeSchema):
logic_operator = fields.String()
这里的问题是,当序列化为 json 时,即使子节点是逻辑节点或值节点(有点符合预期),也只有 Node 的属性存在。我发现了 marshmallow-oneofschema here github 但我无法使用它,因为我必须用它替换:
# In NodeSchema
children = fields.Nested('self', many=True)
与:
class SomeNodeSchema(OneOfSchema):
type_schemas = {
'node': NodeSchema,
'logic_node': LogicNodeSchema,
'value_node': ValueNodeSchema,
}
def get_obj_type(self, obj):
if isinstance(obj, LogicNode):
return 'logic_node'
if isinstance(obj, ValueNode):
return 'value_node'
elif isinstance(obj, Node):
return 'node'
# In NodeSchema
children = fields.Nested(SomeNodeSchema, many=True)
但这会导致循环导入,这使得它不可能。
I found about marshmallow-oneofschema
虽然没有集成到核心,但我认为marshmallow-oneofschema是做多态的推荐方式。
this leads to a circular import
您可以将名称作为字符串传递来解决循环导入问题。
children = fields.Nested('SomeNodeSchema', many=True)