如何在运行时确定 Python 类型注释的类型?

How do I determine the type of a Python type annotation at runtime?

我想检查 class 变量的类型注释,如果它是 typing.Literal,则提取文字值并对其进行处理。但是:

from typing import Literal
class Foo:
    bar: Literal['baz']

l = Foo.__annotations__['bar']
isinstance(l, Literal)

产量:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/tbabb/.pyenv/versions/3.8.5/lib/python3.8/typing.py", line 342, in __instancecheck__
    raise TypeError(f"{self} cannot be used with isinstance()")
TypeError: typing.Literal cannot be used with isinstance()

此外,l.__class__ == LiteralFalse,所以这也不起作用。

为什么 isinstance() 检查不成功?如何检查正在使用的注释类型?

typing_inspect 库通过 checking 注释对象的 __origin__ 属性解决了这个问题。如果 bar 的注释是文字:

,这应该评估为 True
a = Foo.__annotations__['bar']
isinstance(a, Literal[''].__class__) and a.__origin__ is typing.Literal

请注意,仅 isinstance() 是不够的,因为其他类型注释使用相同的 class:

class Z:
    x: Literal['plumbus']
    y: List[int]

axns = Z.__annotations__
axns['x'].__class__ is axns['y'].__class__
> True

这就是为什么 __origin__ 的检查也是必要的。