Python 3.11 多重继承模型的键入

问题描述 投票:0回答:1

我想为一组共享公共元类(

AMeta
)的相关类实现类型化,有两个“事实上的”抽象父类:

  • A
    (:类型[AMeta])
  • ADerived
    - 也继承自另一个类
    C

最后还有

ADerived
D1
D2
,...这些是动态创建的)和
A
E
F
,...)父类的实际实现模型。

A
E
F
)的实现还有一个类型为
ADerived
_DerivedModel
)的类变量,我遇到的问题是试图让
mypy
推断出它们的正确类型。

我知道这段代码可能没有意义,但实际实现更复杂,并且派生模型是动态创建的。这是它的简化:

from __future__ import annotations
from typing import TypeVar, Type, ClassVar

_BModel = TypeVar("_BModel", bound="ADerived")


class C:
    pass


class AMeta(type):
    @property
    def BModel(cls: Type[A]) -> Type[_BModel]:
        return cls._DerivedModel


# Abstract Models
class A(metaclass=AMeta):
    _DerivedModel: ClassVar[Type[_BModel]]


class ADerived(A, C):
    pass


# Derived Models (this models are dynamically created)
class D1(ADerived):
    pass


class D2(ADerived):
    pass


# Implementations


class E(A):
    _DerivedModel = D1


class F(A):
    _DerivedModel = D2


MyDerived1 = E.BModel  # Should be infered by mypy as type[D1]
MyDerived2 = F.BModel  # Should be infered by mypy as type[D2]
python mypy typing
1个回答
0
投票

为了帮助 mypy 在动态创建派生模型的复杂场景中正确推断类型,您可以在元类中使用

Type
函数以及
TypeVar
。以下修改后的代码应该有助于 mypy 正确推断类型:

from __future__ import annotations
from typing import TypeVar, Type, ClassVar, TypeVar, cast

_BModel = TypeVar("_BModel", bound="ADerived")


class C:
    pass


class AMeta(type):
    @property
    def BModel(cls: Type[A]) -> Type[_BModel]:
        return cls._DerivedModel


# Abstract Models
class A(metaclass=AMeta):
    _DerivedModel: ClassVar[Type[_BModel]]


class ADerived(A, C):
    pass


# Derived Models (these models are dynamically created)
class D1(ADerived):
    pass


class D2(ADerived):
    pass


# Implementations
class E(A):
    _DerivedModel = D1


class F(A):
    _DerivedModel = D2


# TypeVar for the dynamically created models
_MyDerived = TypeVar("_MyDerived", D1, D2)

MyDerived1: Type[_MyDerived] = cast(Type[_MyDerived], E.BModel)
MyDerived2: Type[_MyDerived] = cast(Type[_MyDerived], F.BModel)

# Now mypy should correctly infer MyDerived1 as D1 and MyDerived2 as D2.

这使用

TypeVar
_MyDerived
指定动态创建的模型允许的类型。然后使用
cast
函数指导 mypy 推断正确的类型。这应该有助于 mypy 正确地将
MyDerived1
推断为
D1
并将
MyDerived2
推断为
D2

© www.soinside.com 2019 - 2024. All rights reserved.