You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何为函数标注与类成员函数一致的返回类型?

问题描述

我正在使用Python 3.11,搭配mypy作为类型检查器。想要实现如下示例,但不知道foo_call的返回类型该如何定义,才能让它自动根据Foo的泛型参数(比如Bar)推断出my_func的返回类型:

from dataclasses import dataclass
from abc import ABC, abstractmethod
from typing import Any, TypeVar, Generic

class MyBase(ABC):
    @abstractmethod
    def my_func(self, *args, **kwargs) -> Any:
        raise NotImplementedError

class Bar(MyBase):
    def my_func(self, *args, **kwargs) -> int:
        return 5

class Baz(MyBase):
    def my_func(self, *args, **kwargs) -> str:
        return 'Hello'

T = TypeVar('T', bound=MyBase)

@dataclass
class Foo(Generic[T]):
    value: T

    def foo_call(self) -> ???:  # 这里该填什么?我想要类似T.my_func.__annotations__['return']的效果
        return self.value.my_func()

myFoo: Foo[Bar] = Foo(value=Bar())
myFoo.foo_call()  # 希望这里能自动提示返回类型为int

我试过把myFoo声明为Foo[int],并把foo_call的返回类型设为T,但这样当Bar.my_func的返回类型变更时,无法自动同步。正确的实现方式是什么?

编辑补充

之前得到的方法有帮助,但存在两个问题:一是my_func返回类型变更时仍需多处更新类型提示;二是支持多个函数时要定义多个TypeVar,示例如下:

from dataclasses import dataclass
from abc import ABC, abstractmethod
from typing import TypeVar, Generic

# 每新增一个方法就要加一个TypeVar
T = TypeVar('T')
TOther = TypeVar('TOther')

class MyBase(ABC, Generic[T, TOther]):
    @abstractmethod
    def my_func(self, *args, **kwargs) -> T:
        raise NotImplementedError

    @abstractmethod
    def other_func(self, *args, **kwargs) -> TOther:
        raise NotImplementedError

class Bar(MyBase[int, float]):
    def my_func(self, *args, **kwargs) -> int:
        return 5

    def other_func(self, *args, **kwargs) -> float:
        return 6.2


@dataclass
class Foo(Generic[T, TOther]):
    value: MyBase[T, TOther]

    def foo_call(self) -> T:
        return self.value.my_func()

    def foo_other(self) -> TOther:
        return self.value.other_func()

myFoo: Foo[int, float] = Foo(value=Bar())
myFoo.foo_call()
myFoo.foo_other()

我理想的效果是:只需将MyBase的子类类型作为Foo的泛型参数(比如myFoo: Foo[Bar] = ...),让foo_call等方法的返回类型自动据此推断。

解决方案

可以使用typing_extensions.ReturnType(Python 3.12+可直接用typing.ReturnType)来提取类方法的返回类型,无需手动维护多个TypeVar,且能自动同步方法返回类型的变更:

实现代码

from dataclasses import dataclass
from abc import ABC, abstractmethod
from typing import TypeVar, Generic
from typing_extensions import ReturnType  # Python 3.12+ 替换为 from typing import ReturnType

# 定义绑定到MyBase的TypeVar
T = TypeVar('T', bound='MyBase')

class MyBase(ABC):
    @abstractmethod
    def my_func(self, *args, **kwargs) -> Any:
        raise NotImplementedError

    @abstractmethod
    def other_func(self, *args, **kwargs) -> Any:
        raise NotImplementedError

class Bar(MyBase):
    def my_func(self, *args, **kwargs) -> int:
        return 5

    def other_func(self, *args, **kwargs) -> float:
        return 6.2

class Baz(MyBase):
    def my_func(self, *args, **kwargs) -> str:
        return 'Hello'

    def other_func(self, *args, **kwargs) -> bool:
        return True

@dataclass
class Foo(Generic[T]):
    value: T

    # 直接提取T中my_func的返回类型
    def foo_call(self) -> ReturnType[T.my_func]:
        return self.value.my_func()

    # 同理提取other_func的返回类型
    def foo_other(self) -> ReturnType[T.other_func]:
        return self.value.other_func()

# 使用时只需传入子类类型作为泛型参数
myFooBar: Foo[Bar] = Foo(value=Bar())
reveal_type(myFooBar.foo_call())  # mypy会提示:Revealed type is "builtins.int"
reveal_type(myFooBar.foo_other()) # mypy会提示:Revealed type is "builtins.float"

myFooBaz: Foo[Baz] = Foo(value=Baz())
reveal_type(myFooBaz.foo_call())  # mypy会提示:Revealed type is "builtins.str"
reveal_type(myFooBaz.foo_other()) # mypy会提示:Revealed type is "builtins.bool"

说明

  1. 自动同步类型变更:当Bar.my_func的返回类型从int改为str时,myFooBar.foo_call()的类型提示会自动更新,无需修改Foo类的代码。
  2. 无需额外TypeVar:新增方法时,只需在Foo中添加对应方法,用ReturnType[T.新方法名]作为返回类型即可,无需定义新的TypeVar。
  3. 类型检查支持:mypy能正确识别ReturnType[T.方法名]的类型,提供准确的代码提示和类型校验。

内容的提问来源于stack exchange,提问作者Mobious

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 20:07:03