Python 确定数据类型/结构是否与数据的基本描述相同?

Python 确定数据类型/结构是否与数据的基本描述相同?,python,types,structure,verify,Python,Types,Structure,Verify,设想一个简单的数据描述标签,用于描述两个系统之间交换的数据类型。为了保证这些系统之间的数据完整性(也可通过创建新模块进行扩展),它们必须对输出的数据类型和结构进行简单描述。鉴于这些系统主要处理命令行命令和输出,数据类型不必太复杂 因为这个系统使用的语言是Python,所以简单的数据类型是bool、int、float、str、list和dict。列表和dict必须明确定义它们所包含的数据类型(例如,对于float列表来说是list(float),对于映射字符串到字符串列表的字典来说是dict(st

设想一个简单的数据描述标签,用于描述两个系统之间交换的数据类型。为了保证这些系统之间的数据完整性(也可通过创建新模块进行扩展),它们必须对输出的数据类型和结构进行简单描述。鉴于这些系统主要处理命令行命令和输出,数据类型不必太复杂

因为这个系统使用的语言是Python,所以简单的数据类型是bool、int、float、str、list和dict。列表和dict必须明确定义它们所包含的数据类型(例如,对于float列表来说是list(float),对于映射字符串到字符串列表的字典来说是dict(str,list(str))

当一个系统从另一个系统传递数据时,它会检查所传递的数据是否符合模块对其输入的数据描述,如果符合,则继续,否则会抛出错误。下面有几个小示例:

verify("int", 1)                            -> True
verify("int", "1")                          -> False
verify("list(int)", [1, 2, 3])              -> True
verify("list(int)", [])                     -> True
verify("dict(str,int)", {"a": 1})           -> True
verify("dict(str,int)", {"b": 1, "c": "d"}) -> False

显然,如果我从头开始编写递归,它是解决这个问题的方法,这不是一个太难的问题,但我想知道是否已经有了一个用于此类功能的模块。

这是我目前所拥有的,它被更好地打包成了“TypeLabel”对象,但我将其压缩为一个函数,以便更接近答案中使用测试用例指定的函数。该函数通过了上面几个简单的测试用例,但没有提供错误检查,例如不正确的数据类型规范。今天晚些时候我将制作一个更健壮的版本。这不是批评,但如果你看到任何明显的错误,请随意指出

def verify(specification, test_data):
    typenames = {"tuple": tuple, "dict": dict, "list": list, "str": str, "int": int, "bool": bool, "float": float}

    def interpret_spec(spec):
        def find_separators(spec):
            seps = []
            depth = 0
            for i in range(len(spec)):
                if spec[i] == ',' and depth == 0:
                    seps.append(i)
                elif spec[i] == '(':
                    depth += 1
                elif spec[i] == ')':
                    depth -= 1
            return seps

        def recurse_type(spec):
            seps = find_separators(spec)
            if len(seps) != 0:
                sub_specs = [""]
                for i in range(len(spec)):
                    if i in seps:
                        sub_specs.append("")
                    else:
                        sub_specs[-1] += spec[i]
                if spec[-1] == "":
                    spec = spec[:-1]
                return tuple([recurse_type(sub_spec) for sub_spec in sub_specs])
            spec_name = spec
            if "(" in spec:
                spec_name = spec[:spec.find("(")]
                sub_spec = spec[spec.find("(")+1:spec.rfind(")")]
                return {spec_name: recurse_type(sub_spec)}
            else:
                return spec_name

        return recurse_type(spec.replace(" ", "").strip())

    def recurse_verify(spec, data):
        try:
            if isinstance(spec, str):
                return isinstance(data, typenames[spec])
            elif isinstance(spec, dict):
                datatype_name = spec.keys()[0]
                if not isinstance(data, typenames[datatype_name]):
                    return False
                if datatype_name == "list":
                    for item in data:
                        if not recurse_verify(spec[datatype_name], item):
                            return False
                elif datatype_name == "dict":
                    for key in data:
                        if not recurse_verify(spec[datatype_name][0], key) or not recurse_verify(spec[datatype_name][1], data[key]):
                            return False
                elif datatype_name == "tuple":
                    if len(spec[datatype_name]) != len(data):
                        return False
                    for i in range(len(data)):
                        subtype = spec[datatype_name][i]
                        subdata = data[i]
                        if not recurse_verify(subtype, subdata):
                            return False
        except TypeError:
            return False
        else:
            return True

    return recurse_verify(interpret_spec(specification), test_data)

我知道没有模块,但这将是一个有趣而有用的项目检查。如果没有人用一个合理的方案回答这个问题,我会看看我是否能抽出时间来做它。@Goodies我已经基本完成了它的初始创建,我刚刚意识到我可能需要做更多的工作。寻找模块为你做工作对几乎每一个非琐碎的任务都很有用。你可能可以通过m获得一些帮助odule.@Goodies我发布了一个快速的模型,通过了问题中给出的所有测试,我今天晚些时候将要开发一个更健壮的版本。如果你想贡献,这将是一个很好的起点。很好!我甚至可以接受一个附加(自定义)参数类来测试它们。@Goodies这是一个好主意,特别是考虑到我正在寻找一个可扩展的解决方案。