想象一个简单的数据描述标签,用于描述两个系统之间交换的数据类型。为了在这些系统之间具有数据完整性(这些系统也可以通过创建新模块来扩展),它们必须对它们输出的数据类型和结构进行简单描述。鉴于这些系统主要处理命令行命令和输出,数据类型不必太复杂。
因为这个系统编写的语言是Python,所以简单的数据类型是bool,int,float,str,list和dict。列表和dicts必须使用它们包含的数据类型显式定义(即列表(浮点数)用于浮点数列表或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
显然,递归是解决这个问题的方法,如果我从头开始编写它并不是一个问题不太困难,但我想知道是否已经存在这种功能的模块。 / p>
答案 0 :(得分:1)
这就是我到目前为止所做的,它更好地打包成了一个" 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)