首页 > 解决方案 > 如何在 Python 中使用具有泛型函数的泛型类?

问题描述

我很难弄清楚如何表达我的问题,但我有如下代码:

  1. 有一个泛型类 ( BaseOuter) 和一个方法 ( to_inner),其返回类型是泛型的。
  2. 该通用类有具体的子类(例如Outer)。当我调用Outer().to_inner()时,推断的返回类型Inner与我预期的一样。
  3. 我创建了一个通用函数,它接受一个可选参数BaseOuter并调用to_inner()它。但是当我将 an 传递Outer给这个函数时,推断的返回类型是BaseInner,而不是Inner我预期的那样。

难道我做错了什么?有没有办法让类型检查器意识到to_inner(Outer())返回一个Inner

import typing

class BaseInner:
    pass

T_co = typing.TypeVar('T_co', bound=BaseInner, covariant=True)
T = typing.TypeVar('T', bound=BaseInner)


class BaseOuter(typing.Generic[T_co]):
    def to_inner(self) -> T_co:
        return self.InnerType()


@typing.overload
def to_inner(outer: BaseOuter[T]) -> T: ...
@typing.overload
def to_inner(outer: None) -> None: ...
def to_inner(outer: typing.Optional[BaseOuter[T]]) -> typing.Optional[T]:
    return outer.to_inner() if outer else None


class Inner(BaseInner):
    pass


class Outer(BaseOuter[Inner]):
    InnerType = Inner


this_is_an_Inner = Outer().to_inner()
unfortunately_a_BaseInner = to_inner(Outer())

标签: pythonpython-typing

解决方案


您需要为泛型类添加InnerType注释BaseOuter,因为此名称用于to_inner方法中。否则,mypy(0.910) 将无法理解您的意图:

class BaseOuter(typing.Generic[T_co]):
    InnerType: typing.Type[T_co]   # <---
    
    def to_inner(self) -> T_co:
        return self.InnerType()

推荐阅读