如何将 Python 'deque' 对象作为列表理解的一部分

How to prepend a Python 'deque' object as part of a list comprehension

我正在使用 jsonschema 验证 JSON 文档,如果有任何错误我需要捕获它们,包括文档中错误的路径。为确保路径永远不会为空(即,如果文档根目录中的必需键丢失),我希望在错误路径前添加 root.

v = jsonschema.Draft7Validator(schema_dict)
errors = sorted(v.iter_errors(payload_dict), key=lambda e: e.path)

if len(errors) > 0:
    paths = ['.'.join(deque(('root')) + e.absolute_path) for e in errors]
    messages = [f'{p}: {e.message}' for e, p in zip(errors, paths)]
    raise InvalidPayloadException(messages) from None

例如,如果需要属性 obj.key1obj.key2 并且测试了以下 JSON 文档。

{
    "obj": {
       "keyx": "value"
    }
}

我希望messages包含的是以下列表。

["root.obj: 'key1' is a required property", "root.obj: 'key2' is a required property"]

messages实际包含的是root作为四个独立的元素。

["r.o.o.t.obj: 'key1' is a required property", "r.o.o.t.obj: 'key2' is a required property"]

如何修改我的代码,使消息包含预期的文本?最好,我想保持列表理解,因为它们往往易于阅读并且不会占用太多空间,但如果需要,我愿意改变它。


我还看到 deque 的文档提到了 appendleft(),但使用它会导致错误。

paths = ['.'.join(e.absolute_path.appendleft('root')) for e in errors]

TypeError: 'NoneType' object is not iterable

所以,问题是您将单个字符串对象传递给 dequeue 构造函数,它像 Python 中的其他 sequence-like 构造函数一样工作,它接受任意可迭代对象并构造通过迭代可迭代对象出队。

但我注意到您使用了一组额外的括号,所以我认为您打算传递一个单例元组。你实际上需要一个逗号,所以你想要的是:

paths = ['.'.join(deque(('root',)) + e.absolute_path) for e in errors]

注意逗号。 deque(('root')) -> deque(('root',))

不过,我认为这样做会更简洁:

paths = ['.'.join(['root', *e.absolute_path]) for e in errors]