Data transfer objects python

7 способов реализации DTOS в Python и что иметь в виду

Объекты передачи данных являются просто структурами данных, обычно используемые для передачи данных между слоем приложений … Помечено Python, 5days5blogPosts, программирование, обучение.

Объекты передачи данных являются просто структурами данных, обычно используемые для передачи данных между слоями приложений или между сервисами.

Самая простая форма DTO в Python может быть просто Словарь :

Вопросы (среди прочего): Мультипликация, отсутствие печатания, отсутствие специфичности.

Мы будем использовать здесь Место расположения Класс, который может быть модельным классом, управляемым ORM в реальном сценарии:

class Location: def __init__(self, name: str) -> None: self.name = name def __repr__(self) -> str: return f"Location(name=)" def __eq__(self, other: Location) -> bool: return self.name == other.name

Если мы хотим точнее настроить атрибуты DTO, мы можем определить отдельный класс :

class ItemDto: def __init__(self, name: str, location: Location, description: str = "") -> None: self.name = name self.location = location self.description = description

В качестве альтернативы, мы можем использовать kwargs и а .получить () Способ для дополнительных параметров:

class ItemDto: def __init__(self, **kwargs) -> None: self.name = kwargs["name"] self.location = kwargs["location"] self.description = kwargs.get("description", "") itemdto = ItemDto( name="Super Potion", location=Location("Various"), description="Recover 70 HP" )

Хорошо определенные DTOS могут дать нам больше преимуществ, таких как облегчение выполнения сериализации или проверки. Вот несколько примеров использования различных особенностей библиотеки Python Standard и 3-х пакетов для создания лучших DTO.

STDLIB Solutions

Dataclasses.

  • добавлен в Python 3.7 (а затем приндоннул в Python 3.6)
  • создан с помощью @dataclass декоратор
  • По умолчанию добавьте автоматически сгенерированные методы дублирования __init__ , __repr__ и __eq__
  • __init__ Метод принимает все поля в качестве параметров метода и устанавливает их значения для атрибутов экземпляра с тем же именами:
from dataclasses import dataclass @dataclass class ItemDto: name: str location: Location description: str = "" # support both positional and keyword args itemdto = ItemDto( name="Old Rod", location=Location("Vermillion City"), description="Fish for low-level Pokemon", )
  • сгенерировано __repr__ Метод Возвращает строку, содержащую имя класса, имена поля и Представление поля
>>> print(itemdto) ItemDto(name='Old Rod', location=Location(name=Vermillion City), description='Fish for low-level Pokemon')
  • сгенерировано __eq__ Метод сравнивает кортежи класса, содержащие значения поля текущего и другого экземпляра.
itemdto2 = ItemDto( name="Old Rod", location=Location("Vermillion City"), description="Fish for low-level Pokemon", ) >>> itemdto == itemdto2 True
def __eq__(self, other): if other.__class__ is self.__class__: return (self.name, self.location, self.description) == (other.name, other.location, other.description) return NotImplemented
  • Это может быть хорошая идея, чтобы сделать неизведанные экземпляры DTO. Возможно, установив аргумент замороженные к Истинный :
@dataclass(frozen=True) class ItemDto: name: str location: Location description: str = ""
. for field in itemdto: . print(field) . TypeError: 'ItemDto' object is not iterable

NamedTupes.

  • NamedTuple подкласс обычного кортежа
  • Введен в Python 3.0 в качестве фабричного метода в модуле коллекций:
from collections import namedtuple ItemDto = namedtuple("ItemDto", ["name", "location", "description"])
  • Добавлено в Python 3.5 в качестве напечатанной версии в типизированном модуле и позже расширена с вариабельной синтаксисом аннотаций в Python 3.6:
from typing import NamedTuple class ItemDto(NamedTuple): name: str location: Location description: str = "" # support both positional and keyword args itemdto = ItemDto( "X Speed", "Temporarily raise Speed in battle", Location("Celadon Dept. Store") ) >>> print(itemdto) ItemDto(name='X Speed', location='Temporarily raise Speed in battle', description='Celadon Dept. Store')
. for field in itemdto: . print(field) . X Speed Temporarily raise Speed in battle Location(name=Celadon Dept. Store)
  • Поддержите значения по умолчанию, хотя они должны быть определены после любых полей без значения по умолчанию.
Читайте также:  Python module installation windows

Напечатает

from typing import TypedDict class ItemDto(TypedDict): name: str location: Location description: str itemdto = ItemDto( name=»Escape Rope,», location=Location(«Various»), description=»Teleport to last visited Pokemon Center», ) >>> print(itemdto)

  • музей
  • __repr__ и __eq__ обрабатывается
  • ИТИТЕРАЛ в обдумывать вид пути
  • Не поддерживайте значения по умолчанию
  • может обеспечить набрав для существующих словарей
  • Поскольку это все еще словари, в конце концов, они могут быть непосредственно сериализованы для структур данных JSON (Хотя в этом примере мы должны предоставить пользовательский кодировщик для location класс).

3-й пакетные пакеты

привлекать

  • Зависимость от Ptyest , так что есть шанс у вас уже есть в вашем проекте
  • Подобно Dataclasses, на самом деле, библиотека ATTRS была основой для разработки данных о Dataclasses:
import attr @attr.s(frozen=True) class ItemDto: name: str = attr.ib() location: Location = attr.ib() description: str = attr.ib(default="") # also, the dataclasses syntax! @attr.dataclass(frozen=True) class ItemDto: name: str location: Location description: str = ""
  • ATTrs предоставляют некоторые дополнительные функциональные возможности на вершине тех, которые предлагают Dataclasses, такие как проверка времени выполнения и оптимизация памяти (щелевые классы).

Вот пример проверки времени выполнения:

@attr.s(frozen=True) class PokemonDto: name: str = attr.ib() type: str = attr.ib( validator=attr.validators.in_( [ "Fire", "Water", "Electric", "Poison", # . ] ) ) >>> PokemonDto("Charmander", "Fire") PokemonDto(name='Charmander', type='Fire') >>> PokemonDto("Charmander", "Gyarados") ValueError: 'type' must be in ['Fire', 'Water', 'Electric', 'Poison'] (got 'Gyarados')

Будьте выбирать attrs или dataclasses – это в конечном итоге зависит от вашего конкретного случая использования, и если вы можете использовать пакеты 3-го вечеринок в вашем проекте.

Pydantic

  • Fastapi использует pydantic для определения схемы и проверки данных
  • Пядинтинтские применения типа подсказки во время выполнения
  • Рекомендуемый способ создания пидантических моделей – подкласс Пидантик. Базомодель Поэтому все модели наследуют некоторые методы:
from pydantic import BaseModel class PokemonDto(BaseModel): name: str type: str class Config: allow_mutation = False # enforced keyword arguments in case of BaseModel subclass pokemondto = PokemonDto(name="Charizard", type="Fire")
import pydantic @pydantic.dataclasses.dataclass(frozen=True) class PokemonDto: name: str type: str # in this case positional args are allowed PokemonDto("Charizard", "Fire")
from enum import Enum from pydantic import BaseModel class TypeEnum(str, Enum): fire = "Fire" water = "Water" electric = "Electric" poison = "Poison" # . class PokemonDto(pydantic.BaseModel): name: str type: TypeEnum class Config: allow_mutation = False >>> PokemonDto(name="Charizard", type="Fire") PokemonDto(name='Charizard', type=) >>> PokemonDto(name="Charizard", type="Charmeleon") ValidationError: 1 validation error for PokemonDto type value is not a valid enumeration member; permitted: 'Fire', 'Water', 'Electric', 'Poison' (type=type_error.enum; enum_values=[, , , ]) 
>>> PokemonDto(name="Charizard", type="Fire").json() ''

Резюме

Ваш выбор о том, как реализовать DTOS зависят от нескольких обстоятельств – необходим ли вам, среди прочего:

  • неподумность
  • Поддержка значений по умолчанию
  • потери правности
  • сериализация
  • Проверка типа выполнения
  • Оптимизация производительности
  • Другое, более продвинутая конфигуративность.
Читайте также:  Web config and php

Пост изначально вдохновлен Это Reddit Thread.

Читайте ещё по теме:

Источник

Оцените статью