Поля и значения по умолчанию¶
В первой модели приходилось каждый раз передавать active.
Укажем, какое значение использовать, когда аргумент пропущен:
from bytespec import ProtoModel, field
class User(ProtoModel):
name: str
active: bool = field(default=True)
user = User(name="Anna")
decoded = User.decode(user.encode())
print(decoded.active) # True
field() настраивает отдельное поле. Здесь default=True позволяет
не передавать active конструктору. Поле остаётся частью сообщения
и записывается даже тогда, когда использовано значение по умолчанию.
Переданное значение важнее default¶
user = User(name="Anna", active=False)
print(User.decode(user.encode()).active) # False
Default применяется только при пропуске аргумента. Имя name по-прежнему
обязательно. Неизвестный аргумент или пропуск обязательного поля вызывают
TypeError.
Для сериализуемого поля нужен именно field(default=...).
Обычное присваивание active: bool = True оставляет атрибут класса
за пределами сообщения — это не сокращённая запись default.
Порядок полей¶
Без дополнительных настроек поля записываются в порядке объявления. Не переставляйте их, если другая сторона уже читает этот формат.
Если нужен явный порядок, первый аргумент field() задаёт индекс:
class User(ProtoModel):
active: bool = field(1, default=True)
name: str = field(0)
user = User(name="Anna")
print(User.decode(user.encode()).name) # Anna
Несмотря на расположение строк, name с индексом 0 записывается первым.
Индексы должны идти от нуля без повторов и пропусков. Для обычной модели
их можно не указывать; правила смешивания явных и автоматических индексов
собраны в Правила объявления полей.
Когда нужны другие настройки¶
field() также позволяет сделать поле необязательным и изменить его
бинарное представление. К этим настройкам перейдём по мере необходимости.
Точная сигнатура доступна в bytespec.field().
Далее — Числа и другие типы: добавим пользователю числовой идентификатор.