简体   繁体   English

如何在可以接受多种不同类型的python数据类中制作List?

[英]How to make List in python dataclass that can accept multiple different types?

I am creating new data class in python.我正在 python 中创建新的数据类。

@dataclass
class User(Mixin):
  id: int = None
  items: List[DefaultItem] = None

This items is array of DefaultItem objects but I need this to be multiple possible objects like:这个itemsDefaultItem对象的数组,但我需要它是多个可能的对象,例如:

items: List[DefaultItem OR SomeSpecificItem OR SomeOtherItem] = None

How can I do something like this in python?我怎么能在python中做这样的事情?

You can use typing.Union for this.您可以为此使用typing.Union

items: List[Union[DefaultItem, SomeSpecificItem, SomeOtherItem]] = None

And if you are on Python 3.10, they've added a convenient shorthand notation:如果您使用的是 Python 3.10,他们会添加一个方便的速记符号:

items: list[DefaultItem | SomeSpecificItem | SomeOtherItem] = None

Also just as a note: If items is allowed to be None , you should mark the type as Optional .另请注意:如果允许itemsNone ,则应将类型标记为Optional

Also, a note that in Python 3.10, you can also pass the kw_only parameter to the @dataclass decorator to work around the issue which I suspect you're having, wherein all fields in a subclass are required to have a default value when there is at least one field with a default value in the superclass, Mixin in this case.另外,请注意,在 Python 3.10 中,您还可以将kw_only参数传递给@dataclass装饰器以解决我怀疑您遇到的问题,其中子类中的所有字段都需要具有默认值在超类中至少有一个具有默认值的字段,在这种情况下是Mixin

I added an example below to illustrate this a little better:我在下面添加了一个例子来更好地说明这一点:

from dataclasses import dataclass


@dataclass
class Mixin:
    string: str
    integer: int = 222


@dataclass(kw_only=True)
class User(Mixin):
    id: int
    items: list['A | B | C']


class A: ...
class B: ...
class C: ...


u = User(string='abc', id=321, integer=123, items=[])
print(u)

Note that I've also wrapped the Union arguments in a string, so that the expression is forward-declared (ie not evaluated yet), since the classes in the Union arguments are defined a bit later.请注意,我还将Union参数包装在一个字符串中,因此该表达式是前向声明的(即尚未计算),因为Union参数中的类是稍后定义的。

This code works in 3.10 because the kw_only param is enabled, so now only keyword arguments are accepted to the constructor.此代码在 3.10 中有效,因为启用了kw_only参数,因此现在构造函数只接受关键字参数。 This allows you to work around that issue as mentioned, where you would otherwise need to define a default value for all fields in a subclass when there's at least one default field in a parent class.这允许您解决上述问题,否则当父类中至少有一个默认字段时,您需要为子类中的所有字段定义默认值。

In earlier Python versions than 3.10, missing the kw_only argument, you'd expect to run into a TypeError as below:在早期的Python版本比3.10,缺少kw_only说法,你希望碰到一个TypeError如下:

TypeError: non-default argument 'id' follows default argument

The workaround for this in a pre-3.10 scenario is exactly how you had it: define a default value for all fields in the User class as below.在 3.10 之前的场景中解决此问题的方法正是您所拥有的:为User类中的所有字段定义一个默认值,如下所示。

from __future__ import annotations

from dataclasses import dataclass, field


@dataclass
class Mixin:
    string: str
    integer: int = 222


@dataclass
class User(Mixin):
    id: int = None
    items: list[A | B | C] = field(default_factory=list)


class A: ...
class B: ...
class C: ...


u = User('abc', 123, 321)
print(u)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM