Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python在列表理解中引发错误(或更好的选择)_Python_Python 3.x_List Comprehension_Raiseerror - Fatal编程技术网

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

Python在列表理解中引发错误(或更好的选择),python,python-3.x,list-comprehension,raiseerror,Python,Python 3.x,List Comprehension,Raiseerror,我有一个从json字符串读取的嵌套结构,看起来类似于以下内容 [ { "id": 1, "type": "test", "sub_types": [ { "id": "a", "type": "sub-test", "name": "test1" }, { "id": "b", "name": "test2", "key_value_pa

我有一个从json字符串读取的嵌套结构,看起来类似于以下内容

[
  {
    "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"
          }
        ]
      }
    ]
  }
]
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']
]
我需要提取和透视数据,准备插入数据库

[
  (1, "b", 0, "Zero"),
  (1, "b", 1, "One")
]
我正在做下面的事情

[
  {
    "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"
          }
        ]
      }
    ]
  }
]
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']
]
这是可行的,但它会对每一个键-值-对进行检查,这感觉是多余的。(每组键值对可能有数千对,只需检查一次就可以知道它们都正常。)

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

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

  • 更优雅
  • 更具可扩展性
  • 性能更好
  • 更多的“蟒蛇”

您应该了解如何验证
json
数据,并使用 此库允许您设置所需的键、指定默认值、添加类型验证等

该库的python实现如下:

示例:

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)

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

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']
]

你可以尝试一种类似于

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))
的操作。在我看来,这仍然比使用普通函数和手动创建列表更干净——它仍然将“处理”和“收集”问题区分开来。

请尝试codereview.SE。我会投票决定关闭,但是迁移选项非常有限(而且我选择了一个奇怪的选项)。有副作用的理解很烦人。Python不是lisp。您应该了解如何验证
json
数据,并使用此库指定显式模式约束。这里有它的Python实现:@mihaandrei他们正在构建一个列表,因为他们需要一个列表,这不是副作用。唯一可以解释的是错误处理,可以在迭代开始之前执行一次。这将调用json中每行的测试类型。@BearBrown您是指外部列表中的每一个dict吗?是的,我认为这就是重点。是的,我认为这样做,但您的解决方案应该有助于OP。是的,这可能是“正确”的方法,而不是试图将转换和验证结合到数据结构的单个过程中。(我倾向于在不需要的地方尝试微观优化。)我喜欢,除了一个警告
validate_last()
需要与
t
一起提供,以便在我的示例中强制执行约束。(
'test'
类型很好,当
t['type']=='test'
时,底层的
键值对被限制为“非法”)