我可以作为一个可选参数在dataclasses中吗?在转换成字典时被省略?

15

我希望能够对一些字典执行静态类型检查(使用vscode里的pylance)。 "棘手" 的部分是,我希望其中一些参数是可选的,且在字典中不显示。 我尝试过使用dataclassesTypedDict,但到目前为止都没有成功。

from typing import Optional, List
from dataclasses import dataclass, asdict


@dataclass
class SubOrder:
    name: str


@dataclass
class Order:
    name: str
    sub_orders: Optional[List[SubOrder]]


assert asdict(Order(name="Pizza")) == {"name": "Pizza"}
assert asdict(Order(name="Pizza", sub_orders=[SubOrder(name="Pasta")])) == {
    "name": "Pizza",
    "sub_orders": [{"name": "Pasta"}],
}

能否使用 dataclasses 实现这一目标?我基本上只想让我的静态类型检查器(pylance / pyright)检查我的字典,这就是我使用 dataclasses 的原因。我也尝试过用 TypedDict,但类型检查器似乎没有像我想象的那样工作。它们总是要求我设置sub_orders
下面的代码可以通过,但是 pylance 对于没有sub_order并不满意。
from typing import Optional, List, TypedDict


class SubOrder(TypedDict):
    name: str


class Order(TypedDict):
    name: str
    sub_orders: Optional[List[SubOrder]]


assert Order(name="Pizza") == {"name": "Pizza"}
assert Order(name="Pizza", sub_orders=[SubOrder(name="Pasta")]) == {
    "name": "Pizza",
    "sub_orders": [{"name": "Pasta"}],
}

编辑

我已经在pylance中添加了一个错误报告,因为这可能实际上是pylance / pyright中的错误。


看起来最好给sub_orders设置一个default_factorylist,而不是将其标记为Optional - user2357112
Optional[Whatever]并不意味着可选。它的意思是Union[Whatever, None] - user2357112
但是那样我会得到一个不同的字典。我需要sub_orders根本不是字典的一部分。 - mr.bjerre
2个回答

11
from dataclasses import asdict, dataclass
from typing import List, Optional

from validated_dc import ValidatedDC


@dataclass
class SubOrder(ValidatedDC):
    name: str


@dataclass
class Order(ValidatedDC):
    name: str
    sub_orders: Optional[List[SubOrder]] = None

    def as_dict(self):
        data = asdict(self)
        return {key: value for key, value in data.items() if value is not None}


data = {'name': 'pizza'}
order = Order(**data)
assert order.get_errors() is None
assert asdict(order) == {'name': 'pizza', 'sub_orders': None}
assert order.as_dict() == {'name': 'pizza'}

data = {'name': 'pizza', 'sub_orders': [{'name': 'pasta'}]}
order = Order(**data)
assert order.get_errors() is None
assert asdict(order) == {'name': 'pizza', 'sub_orders': [{'name': 'pasta'}]}
assert isinstance(order.sub_orders[0], SubOrder)

ValidatedDC - https://github.com/EvgeniyBurdin/validated_dc

ValidatedDC是一个开源的IT工具,可用于校验数据中心的配置文件。您可以在Github上找到它。


谢谢。我应该提到最好不要使用任何第三方库,或者至少只使用已经被广泛认可的库。不好意思,但还是谢谢! - mr.bjerre
你只需要一个文件:https://github.com/EvgeniyBurdin/validated_dc/blob/master/validated_dc.py - Evgeniy_Burdin

9

您可以通过将数据类中的参数设置为空字符串来设置可选参数,例如:

from dataclasses import dataclass
@dataclass
class SubOrder:
    name: str=""

3
这个问题需要使用字符串作为参数吗?使用None来代替非字符串类型的通用参数是可行的吗? - John Smith
当然可以。 - undefined
这是一个专业的翻译引擎,我将为您提供英文到中文的翻译。请注意,我只会翻译文本内容,不会对其进行解释。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接