Ошибки Python Raising в пределах понимания списка (или лучшая альтернатива) - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть вложенная структура, считанная из строки 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"
          }
        ]
      }
    ]
  }
]

Мне нужно извлечь и развернуть данные, готовые для вставки в базу данных...

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

Это работает, но оно выполнит проверку для каждой пары key_value_pair, которая кажется избыточной. (Каждый набор пар ключ-значение может иметь тысячи пар, и проверку нужно выполнить только один раз, чтобы убедиться, что все в порядке.)

Кроме того, будут другиеправила, подобные этому, которые применяются на разных уровнях иерархии.Такие, как «тестовые» типы, могут содержать только «sub_test» sub_types.

Какие есть варианты, кроме указанных выше?

  • Более элегантно?
  • Более расширяемо?
  • Больше производительности?
  • Больше "Pythonic"?

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019

Я бы просто использовал простой цикл, но вы можете добавить его к первой условной проверке, если поместите оператор в функцию:

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']
]
0 голосов
/ 05 февраля 2019

Вы можете попробовать архитектуру в соответствии с

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)).На мой взгляд, это все же чище, чем использование обычной функции и составление списка вручную - он по-прежнему отделяет задачи «обработка» от «сбора».

0 голосов
/ 05 февраля 2019

Вы должны прочитать о том, как проверить ваши json данные и указать явные ограничения схемы с помощью JSON Schema Эта библиотека позволяет вам устанавливать необходимые ключи, указывать значения по умолчанию, добавлять проверку типа и т. Д.

Эта библиотека имеет реализацию Python здесь: пакет jsonschema

ПРИМЕР:

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)
...