内置解决方案,用于验证字典

时间:2018-05-19 01:30:39

标签: python python-3.x

我使用以下代码来验证字典(a)与另一个字典(check_against)的对比。不幸的是我的代码不是很易读,所以我想知道是否有更快/更清晰的内置解决方案来实现相同的结果。也许我还没有使用正确的关键字搜索,但我还没有找到任何关于我认为是一项相当普遍的任务的讨论。

check_against = {
    'a' : str,
    'b' : {
        'c': int,
        'd': int,
    }
}

a = {
   'a' : 1,
   'c' : 1
}

def get_type_at_path(obj, chain):
    _key = chain.pop(0)
    if _key in obj:
        return key_exists(obj[_key], chain) if chain else type(obj[_key])

def root_to_leaf_paths(tree, cur=()):
    if isinstance(tree,dict):
        for n, s in tree.items():
            for path in root_to_leaf_paths(s, cur+(n,)):
                yield path
    else:
        yield [cur,tree]

for path,value_type in root_to_leaf_paths(check_against):
    a_value_type = get_type_at_path(a,list(path))
    if a_value_type == None:
        print(f"Missing key at path \"{list(path)}\"")
    elif not a_value_type == value_type:
        print(f"Value at path \"{list(path)}\" should be of type \"{value_type}\" but got {a_value_type}")

输出

Value at path "['a']" should be of type "<class 'str'>" but got <class 'int'>
Missing key at path "['b', 'c']"
Missing key at path "['b', 'd']"

2 个答案:

答案 0 :(得分:2)

您可以稍微调整<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="@integer/config_shortAnimTime"> <translate android:fromYDelta="-20%" android:toYDelta="0" android:interpolator="@android:anim/decelerate_interpolator" /> <alpha android:fromAlpha="0" android:toAlpha="1" android:interpolator="@android:anim/decelerate_interpolator" /> <scale android:fromXScale="105%" android:fromYScale="105%" android:toXScale="100%" android:toYScale="100%" android:pivotX="50%" android:pivotY="50%" android:interpolator="@android:anim/decelerate_interpolator" /> </set> 功能,将其视为一般字典拼合器。展平架构和数据。然后比较是微不足道的。

root_to_leaf_paths()

答案 1 :(得分:1)

您可以将check_against词典展平为仅包含映射到类型的键,然后针对a运行:

check_against = {'a': <class 'str'>, 'b': {'c': <class 'int'>, 'd': <class 'int'>}}
a = {'a': 1, 'c': 1}
def flatten(d):
  _v = [[(a, b)] if not isinstance(b, dict) else flatten(b) for a, b in d.items()]
  return [i for b in _v for i in b]

new_check = dict(flatten(check_against))
for c, d in a.items():
  if not isinstance(d, new_check[c]):
    raise TypeError("At key '{}': expecting value of type '{}', got '{}'".format(c, new_check[c].__name__, type(d).__name__))

运行时,检查成功引发错误类型的错误:

TypeError: At key 'a': expecting value of type 'str', got 'int'

编辑:利用a作为检查词典:

def check_values(d, check_dict = a):
  for a, b in d.items():
     if a in check_dict and not isinstance(check_dict[a], b):
        raise TypeError("At key '{}': expecting type '{}' but got '{}'".format(a, type(check_dict[a]).__name__, b.__name__))
     if isinstance(b, dict):
       check_values(b)

输出:

TypeError: At key 'a': expecting type 'int' but got 'str'