Предположим, что простая схема определена в marshmallow.
class AddressSchema(Schema):
street=fields.String(required=True)
city=fields.String(required=True)
country=fields.String(default='USA')
class PersonSchema(Schema):
name=fields.String(required=True)
address=fields.Nested(AddressSchema())
Вариант использования здесь — приложения, работающие с объектами в памяти, и сериализация/десериализация в JSON, то есть без базы данных SQL.
Используя стандартную библиотеку json
, я могу анализировать объекты JSON, которые соответствуют этой схеме, и получать доступ к объектам способом, например person1['address']['city']
, но использование подверженных опечаткам строк в подробном синтаксисе несколько неудовлетворительно.
ОО модель ручной работы
Я мог бы определить параллельную объектно-ориентированную модель и аннотировать свою схему декораторами @post_load
, например:
class Address(object):
def __init__(self, street, city, country='USA'):
self.street=street
self.city=city
self.country=country
class Person(object):
def __init__(self, street, city=None):
self.street=street
self.city=city
Но повторение не очень приятно (и я даже не включил описания в схему).
Нет ОО модели
Возможно, явная объектно-ориентированная модель мало что дает — это базовые средства доступа к данным, никакого поведения. Я мог бы получить немного синтаксического сахара, используя jsobject, чтобы написать, например, person1.address.city
. Но и это кажется не совсем правильным. Как разработчик, у меня нет явного API-интерфейса класса python, с которым можно было бы проконсультироваться, чтобы определить, какие поля использовать, я могу ссылаться на схему зефира, но это кажется очень косвенным.
Генерация кода
Было бы довольно легко сгенерировать приведенный выше объектно-ориентированный код из определений схемы зефира. Я удивлен, что такой библиотеки нет. Возможно, генерация кода считается очень непитоновской? Конечно, это подходит только для определений классов стиля доступа к данным; добавление неуниверсального поведения было бы строго нет-нет.
Пользователям кода не нужно было бы знать, что использовался подход codegen — все было бы там с явным API, с документами, видимыми вместе с остальным кодом в readthedocs и т. д.
Динамические классы
Другим подходом могут быть динамические классы, производные от определений зефира. Опять же, насколько я могу судить, такой библиотеки нет (хотя диапазон подходов динамической генерации классов в python впечатляет, возможно, я что-то упустил). Возможно, это не принесет вам многого по сравнению с подходом jsobjects, но могут быть некоторые преимущества - можно было бы переплести это с некоторым явным кодом с определенным поведением. Недостатком динамического подхода является то, что в мире Python явное предпочтение отдается неявному.
Что самое питоническое?
Отсутствие библиотек здесь означает, что я либо чего-то не нахожу, либо не смотрю на это с подходящей питонической точки зрения. Я рад внести свой вклад в pypi, но прежде чем добавить еще одну мета-OO-библиотеку, я хотел убедиться, что я провел здесь должную осмотрительность.