如何使用输入Python模块执行类型检查?

Hug*_*res 8 python typing

我正在阅读输入模块代码,并查看mypy以了解它是如何进行类型检查的.对我来说不幸的是,mypy构建一个非常智能的树,其中包含我仍然不理解的类型表达式,并且它都基于静态分析.

我想在Python中实现一个动态(无静态分析)的类型检查系统.假设调用执行类型检查的函数check_type,我想完成以下操作:

>>> import typing
>>>
>>> check_type(1, int)
True
>>> check_type(1, float)
False
>>> check_type([1], typing.List[int])
True
>>> check_type([1], typing.List[float])
False
>>> check_type([1], typing.List[typing.Any])
True
>>> check_type((1,), typing.Tuple[int])
True
Run Code Online (Sandbox Code Playgroud)

我考虑过从其值重新创建对象类型,例如:

>>> get_type([1])
typing.List<~T>[int]
Run Code Online (Sandbox Code Playgroud)

但这不适用于issubclass:

>>> issubclass(typing.List[int], typing.List[typing.Any])
False
Run Code Online (Sandbox Code Playgroud)

我没有看到在Python中检查类型的简单方法,而没有假设很多关于stdlib模块内部的typing东西(例如,访问__args____tuple_params__).

如何正确实现check_type适用于之前列出的案例的功能?我使用的是Python 2.7.

max*_*max 4

您可以轻松获得非常有限的功能,该功能对于您的问题中提供的简单示例可以正常工作:

import mypy.api

def check_type(value, typ):
    program_text = 'from typing import *; v: {} = {}'.format(typ, repr(value))
    normal_report, error_report, exit_code = mypy.api.run(['-c', program_text])
    return exit_code == 0

int_ = 1
str_ = 'a'
list_str_ = ['a']
list_int_ = [1]
tuple_int_ = (1,)

assert check_type(int_, 'int')
assert not check_type(str_, 'int')
assert check_type(list_int_, 'List[int]')
assert not check_type(list_str_, 'List[int]')
assert check_type(list_int_, 'List[Any]')
assert check_type(tuple_int_, 'Tuple[int]')
Run Code Online (Sandbox Code Playgroud)

您甚至可以通过稍微扩展此代码来执行一些更高级的操作(例如,引用与您在程序中定义的类相对应的类型),以便 mypy 能够解析整个源代码,而不是仅解析当前行。

或者,您可能想查看forcetypeguard