代码之家  ›  专栏  ›  技术社区  ›  MatBailie

Python在列表理解中引发错误(或更好的选择)

  •  1
  • MatBailie  · 技术社区  · 6 年前

    [
      {
        "id": 1,
        "type": "test",
        "sub_types": [
          {
            "id": "a",
            "type": "sub-test",
            "name": "test1"
          },
          {
            "id": "b",
            "name": "test2",
            "key_value_pairs": [
              {
                "key": 0,
                "value": "Zero"
              },
              {
                "key": 1,
                "value": "One"
              }
            ]
          }
        ]
      }
    ]
    

    我需要提取和透视数据,准备插入数据库。。。

    [
      (1, "b", 0, "Zero"),
      (1, "b", 1, "One")
    ]
    

    我正在做下面的事情。。。

    data_list = [
      (
        type['id'],
        sub_type['id'],
        key_value_pair['key'],
        key_value_pair['value']
      )
      for type in my_parsed_json_array
      if 'sub_types' in type
      for sub_type in type['sub_types']
      if 'key_value_pairs' in sub_type
      for key_value_pair in sub_type['key_value_pairs']
    ]
    

    然而,我接下来需要做的是实施一些约束。例如

    if type['type'] == 'test': raise ValueError('[test] types can not contain key_value_pairs.')
    

    但我无法理解。我不想求助于循环。到目前为止,我最好的想法是。。。

    def make_row(type, sub_type, key_value_pair):
        if type['type'] == 'test': raise ValueError('sub-types of a [test] type can not contain key_value_pairs.')
        return (
            type['id'],
            sub_type['id'],
            key_value_pair['key'],
            key_value_pair['value']
        )
    
    data_list = [
      make_row(
        type,
        sub_type,
        key_value_pair
      )
      for type in my_parsed_json_array
      if 'sub_types' in type
      for sub_type in type['sub_types']
      if 'key_value_pairs' in sub_type
      for key_value_pair in sub_type['key_value_pairs']
    ]
    

    这是可行的,但它会对每一个键-值-对进行检查,这感觉是多余的。 (每组键值对可能有数千对,只需检查一次就可以知道它们都正常。)

    此外,还有其他类似的规则,适用于层次结构的不同级别。例如,“测试”类型只能包含“子测试”子类型。

    除上述选项外,还有哪些其他选项?

    • 性能更好?
    3 回复  |  直到 6 年前
        1
  •  1
  •   user10640506 user10640506    6 年前

    json 数据并使用指定显式模式约束 JSON Schema 此库允许您设置所需的键、指定默认值、添加类型验证等。

    该库的python实现如下: jsonschema package

    例子:

    from jsonschema import Draft6Validator
    
    schema = {
        "$schema": "https://json-schema.org/schema#",
    
        "type": "object",
        "properties": {
            "name": {"type": "string"},
            "email": {"type": "string"},
        },
        "required": ["email"]
    }
    Draft6Validator.check_schema(schema)
    
        2
  •  1
  •   juanpa.arrivillaga    6 年前

    我只想使用普通循环,但如果将语句放入函数中,可以将其添加到第一个条件检查中:

    def type_check(type):
        if type['type'] == 'test':
            raise ValueError('sub-types of a [test] type can not contain key_value_pairs.')
        return True
    
    
    data_list = [
      (
        type['id'],
        sub_type['id'],
        key_value_pair['key'],
        key_value_pair['value']
      )
      for type in my_parsed_json_array
      if 'sub_types' in type
      for sub_type in type['sub_types']
      if  'key_value_pairs' in sub_type and type_check(type)
      for key_value_pair in sub_type['key_value_pairs']
    ]
    
        3
  •  1
  •   Karl Knechtel    6 年前

    你可以尝试一种类似于

    def validate_top(obj):
        if obj['type'] in BAD_TYPES:
            raise ValueError("oof")
        elif obj['type'] not in IRRELEVANT_TYPES: # actually need to include this
            yield obj
    
    def validate_middle(obj):
        # similarly for the next nested level of data
    
    # and so on
    
    [
        make_row(r)
        for t in validate_top(my_json)
        for m in validate_middle(t)
        # etc...
        for r in validate_last(whatever)
    ]
    

    我这里的一般模式是使用生成器(函数,而不是表达式)来 信息技术

    在更简单的情况下,如果不值得将多个处理级别分开(或者它们不是自然存在的),您仍然可以编写一个生成器并执行以下操作 list(generator(source)) . 在我看来,这仍然比使用普通函数和手动构建列表更干净——它仍然将“处理”和“收集”问题分开。