如何在 NamedTuple 中键入函数属性

How to type a function attribute in NamedTuple

我有一段代码像

from typing import Callable, NamedTuple, TypeVar


def f1(x: int) -> int:
    return x


def f2(y: str) -> int:
    return len(y)


T = TypeVar("T", int, str)


class Config(NamedTuple):
    func: Callable[[T], int]


c1 = Config(func=f1)
c2 = Config(func=f2)

Mypy 抱怨:

toy.py:19:18: error: Argument "func" to "Config" has incompatible type "Callable[[int], int]"; expected "Callable[[Config], int]"
toy.py:20:18: error: Argument "func" to "Config" has incompatible type "Callable[[str], int]"; expected "Callable[[Config], int]"
Found 2 errors in 1 file (checked 1 source file)

为什么会期望 "Callable[[Config], int]"

我正在使用 Python-3.8,而 mypy==0.800

如果您希望该字段的类型是 int 的函数或 str 的函数,您可以执行

class Config(NamedTuple):
    func: Callable[[int], int] | Callable[[str], int]

这描述了两种函数类型的结合。

但是,这不是一个有用的类型。如果 Python 有交集类型,这将等同于

Callable[[int & str], int]

int & str 是空类型。没有同时为 intstr 的值。所以这是一种永远不能调用的函数。 isinstance 在这里帮不了你,因为你无法对 Callable.

的声明参数类型进行类型检查

如评论中所说,可以做到

Callable[[int | str], int]

但这是接受 int 或字符串 的函数类型,而不是只选择性地接受两者之一的函数类型。