你想要一个
受歧视的工会
(也称为
tagged union
).
在受歧视的工会中,存在
鉴别器
(也称为a
标签字段
)其可用于区分成员。
您当前有一个联盟
Foo
和
Bar
,你想用
.type
属性。但是,此字段不能作为鉴别器,因为它对联盟的每个成员都没有不同。
(游乐场:
Pyright
,
Mypy
)
for i in (Foo(Type.FOO), Bar(Type.BAR)):
reveal_type(i) # Foo | Bar
mischievous_foo = Foo(Type.BAR) # This is valid
naughty_bar = Bar(Type.FOO) # This too
for i in (mischievous_foo, naughty_bar):
if i.type == Type.FOO:
reveal_type(i) # Runtime: Bar, not Foo
如果
Foo.type
只能是
Type.FOO
和
Bar.Type
是
Type.BAR
,那么在类型中反映这一点很重要:
(制作
type
此时,数据类字段不再有意义,但我假设就这个问题而言,它们只是数据类。)
@dataclass
class Foo:
type: Literal[Type.FOO]
@dataclass
class Bar:
type: Literal[Type.BAR]
As
Literal[Type.FOO]
和
Literal[Type.BAR]
是不相交类型,
i
然后通过检查类型来缩小范围
.type
:
(游乐场:
Pyright
,
Mypy
)
for i in (Foo(Type.FOO), Bar(Type.BAR)):
if i.type == Type.FOO:
reveal_type(i) # Foo
Foo(Type.BAR) # error
Bar(Type.FOO) # error
…即使在发电机中,是的:
item = next(i for i in (Foo(Type.FOO), Bar(Type.BAR)) if i.type == Type.BAR)
reveal_type(item) # Bar