Python 中泛型的类型提示参数默认值

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

我有一些代码可归结为以下内容:

from typing import Callable, TypeVar

T = TypeVar("T")

def default_fn() -> str:
    return "Hello world!"

def call_fn(fn: Callable[[], T] = default_fn) -> T:
    return fn()

注意,我使用的是 Python 3.10,因此我无法尝试新的 3.12 泛型语法。

问题的焦点是非常通用的

call_fn
函数,我希望使用通用类型提示来显示参数的返回类型与
call_fn
的返回类型相匹配。我还想要一个默认参数,这里是
default_fn
。令我惊讶的是,Mypy(1.2.0,如果相关的话)对此抱怨:

$ mypy foo.py
foo.py:8: error: Incompatible default for argument "fn" (default has type "Callable[[], str]", argument has type "Callable[[], T]")  [assignment]
Found 1 error in 1 file (checked 1 source file)

(第8行是

def call_fn...
线)

修复此错误(或修复此代码)的最“Pythonic”方法是什么?我遇到的修复都有某种缺点:

  1. default_fn
    的返回类型替换为
    Any

这个选项并不是世界上最糟糕的事情,但据我了解,当你可以更精确时,

Any
应该避免使用,尤其是对于返回类型。

  1. 将第 8 行出现的两次
    T
    替换为
    T | str
    ,或者无论默认函数的返回类型是什么

这有点难看,而且读起来也很混乱(当你已经使用泛型类型时,为什么还需要指定类型?)

  1. 不使用默认函数,而是将参数设置为
    Optional[Callable[[], T]] = None
    ,并使用函数体将参数设置为
    default_fn

这不是可怕,还有其他原因使用此模式,例如当您希望默认值是可变的时。尽管如此,它比在通常的地方(即在函数签名中)使用默认函数更难阅读,这只是一种常见模式,因为在这些情况下它是必要

python generics mypy
1个回答
0
投票

我会选择第四个选项..使用

typing.overload
。您可以指定当没有参数时返回 str,否则它是参数上的通用函数。实际实现可以设置返回
Any
.

from typing import Callable, TypeVar, overload, Any

T = TypeVar("T")


def default_fn() -> str:
    return "Hello world!"


@overload
def call_fn() -> str:
    ...


@overload
def call_fn(fn: Callable[[], T]) -> T:
    ...


def call_fn(fn: Callable = default_fn) -> Any:
    return fn()
© www.soinside.com 2019 - 2024. All rights reserved.