在嵌套 class 中使用抽象外部 class 的子classes
Use subclasses of abstract outer class in nested class
我想在 pydantic class 的嵌套配置 class 中使用抽象 class 的所有子class,如下所示:
def custom_json_loads(classes, ....):
##use classes here for json parsing
class Outer(BaseModel, abc.ABC):
name = "test"
class Config:
json_loads = partial(custom_json_loads, Outer.__subclasses__)
这一切的目的是我知道我的 JSON 的 OuterClass 类型和 classes 的名称表示应该创建子 class 的哪个实例
例如我有 BlueOuter、RedOuter、GreenOuter,在 json 中会有
“外”:{
“名称”:“BlueOuter”,
....}
但我不想导入所有可能的子class变体,因为它们会随着时间的推移而进化
为什么不使用 discriminated union?
import abc
from typing import Annotated, Literal, Union
from pydantic import BaseModel, Field
class Outer(BaseModel, abc.ABC):
...
class BlueOuter(Outer):
name: Literal["BlueOuter"]
class RedOuter(Outer):
name: Literal["RedOuter"]
class GreenOuter(Outer):
name: Literal["GreenOuter"]
OuterUnion = Annotated[
Union[BlueOuter, RedOuter, GreenOuter], Field(discriminator="name")
]
class Foo(BaseModel):
outer: OuterUnion
print(Foo.parse_raw('{"outer": {"name": "BlueOuter"}}'))
print(Foo.parse_raw('{"outer": {"name": "RedOuter"}}'))
print(Foo.parse_raw('{"outer": {"name": "GreenOuter"}}'))
输出:
outer=BlueOuter(name='BlueOuter')
outer=RedOuter(name='RedOuter')
outer=GreenOuter(name='GreenOuter')
如果您担心在添加新的 Outer
子类时需要维护 OuterUnion
,您可以进行单元测试来检查 OuterUnion
是否包含 Outer
:
class OrangeOuter(Outer):
name: Literal["OrangeOuter"]
outer_union_classes = OuterUnion.__args__[0].__args__
for subclass in Outer.__subclasses__():
assert (
subclass in outer_union_classes
), f"{subclass.__name__} must be a member of OuterUnion (classes: {[c.__name__ for c in outer_union_classes]}). Please add it."
输出:
AssertionError: OrangeOuter must be a member of OuterUnion (classes: ['BlueOuter', 'RedOuter', 'GreenOuter']). Please add it.
我想在 pydantic class 的嵌套配置 class 中使用抽象 class 的所有子class,如下所示:
def custom_json_loads(classes, ....):
##use classes here for json parsing
class Outer(BaseModel, abc.ABC):
name = "test"
class Config:
json_loads = partial(custom_json_loads, Outer.__subclasses__)
这一切的目的是我知道我的 JSON 的 OuterClass 类型和 classes 的名称表示应该创建子 class 的哪个实例
例如我有 BlueOuter、RedOuter、GreenOuter,在 json 中会有 “外”:{ “名称”:“BlueOuter”, ....}
但我不想导入所有可能的子class变体,因为它们会随着时间的推移而进化
为什么不使用 discriminated union?
import abc
from typing import Annotated, Literal, Union
from pydantic import BaseModel, Field
class Outer(BaseModel, abc.ABC):
...
class BlueOuter(Outer):
name: Literal["BlueOuter"]
class RedOuter(Outer):
name: Literal["RedOuter"]
class GreenOuter(Outer):
name: Literal["GreenOuter"]
OuterUnion = Annotated[
Union[BlueOuter, RedOuter, GreenOuter], Field(discriminator="name")
]
class Foo(BaseModel):
outer: OuterUnion
print(Foo.parse_raw('{"outer": {"name": "BlueOuter"}}'))
print(Foo.parse_raw('{"outer": {"name": "RedOuter"}}'))
print(Foo.parse_raw('{"outer": {"name": "GreenOuter"}}'))
输出:
outer=BlueOuter(name='BlueOuter')
outer=RedOuter(name='RedOuter')
outer=GreenOuter(name='GreenOuter')
如果您担心在添加新的 Outer
子类时需要维护 OuterUnion
,您可以进行单元测试来检查 OuterUnion
是否包含 Outer
:
class OrangeOuter(Outer):
name: Literal["OrangeOuter"]
outer_union_classes = OuterUnion.__args__[0].__args__
for subclass in Outer.__subclasses__():
assert (
subclass in outer_union_classes
), f"{subclass.__name__} must be a member of OuterUnion (classes: {[c.__name__ for c in outer_union_classes]}). Please add it."
输出:
AssertionError: OrangeOuter must be a member of OuterUnion (classes: ['BlueOuter', 'RedOuter', 'GreenOuter']). Please add it.