Python 中使用 Mypy 的“除类之外的任何可调用对象”的类型注释是什么?

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

我正在尝试完美地键入注释以下 Python 函数:

from typing import Callable, Any
import inspect

def foo(func: Callable[..., Any]) -> None:
    if inspect.isclass(func):
        raise ValueError
    # Do something...

class Bad:
    pass

def good() -> Bad:
    return Bad()


foo(good)  # OK
foo(Bad)   # NOK

我想缩小

Callable[..., Any]
类型的范围,以便它拒绝作为参数传递的
Bad

请参阅 Mypy 游乐场此处

我在

typing
模块和 Mypy 文档中找不到任何东西来区分简单函数和类。这可能吗?

不清楚为什么

type(Bad)
type(good)
在运行时非常不同,但我找不到类型注释的等效项。

python python-3.x type-hinting mypy
1个回答
0
投票

如您所知,

Callable
是一种结构类型,因此任何具有
__call__
实例方法的东西(包括所有类,因为类是
type
的实例,并且
type.__call__
允许您使用调用语法
Bad()
) 将满足
Callable
.

Python 类型系统不完全支持静态键入某些内容以对类型的子集进行不同的行为;例如,如果您尝试输入“”整数而不是“

0
”,您也会遇到同样的问题。最接近的是用
@typing.overload
创建
typing.Never
,这表示
foo
在运行时会出错,无论如何,这就是你对
foo
的实现。在这里,mypy 将在调用站点预计在运行时失败后的第一行抛出错误(示例在 mypy-playground 中给出,复制如下):

from typing_extensions import Callable, Any, overload, Never
import inspect

@overload
def foo(func: type) -> Never: ...

@overload
def foo(func: Callable[..., Any]) -> None: ...

def foo(func: Callable[..., Any]) -> None:
    if inspect.isclass(func):
        raise ValueError
    # Do something...

class Bad:
    pass

def good() -> Bad:
    return Bad()


foo(good)  # OK
foo(Bad)   # NOK
a = 3  # mypy: Statement is unreachable [unreachable]

这需要指定

--warn-unreachable
CLI 选项或
warn_unreachable = True
配置文件选项才能工作。

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