使用PEP 563检查签名

Tob*_*ann 5 python types static-typing python-3.x python-3.7

如下代码:

import inspect
from typing import NamedTuple

class Example(NamedTuple):
    a: str

if __name__== "__main__":
    signature: inspect.Signature = inspect.signature(Example)
    print(signature)
Run Code Online (Sandbox Code Playgroud)

输出:

(a: str)
Run Code Online (Sandbox Code Playgroud)

但是,在启用PEP 563 –推迟评估注释时

from __future__ import annotations
import inspect
from typing import NamedTuple

class Example(NamedTuple):
    a: str

if __name__== "__main__":
    signature: inspect.Signature = inspect.signature(Example)
    print(signature)
Run Code Online (Sandbox Code Playgroud)

输出为:

(a: 'str')
Run Code Online (Sandbox Code Playgroud)

我如何才能inspect.Signature像没有PEP 563一样获得类型完全相同的对象?

Mar*_*ers 5

除非需要,否则使用 PEP 536 的目的是不要评估注释。签名仅报告注释。

如果出于您的目的,您需要解析注释,您必须自己这样做。PEP 536 告诉文档您如何执行此操作

对于使用类型提示的代码,该typing.get_type_hints(obj, globalns=None, localns=None)函数从其字符串形式正确计算表达式。

[...]

对于将注释用于其他目的的代码,常规的 eval(ann, globals, locals) 调用足以解析注释。

您甚至可以在获取签名之前使用该typing.get_type_hints()函数进行分配__annotations__

import typing

Example.__new__.__annotations__ = typing.get_type_hints(Example.__new__)
signature: inspect.Signature = inspect.signature(Example)
Run Code Online (Sandbox Code Playgroud)

即使from __future__ import annotations没有使用过,这样做也是安全的。