Как определить пользовательские типы данных в Python?

Ответ

В Python пользовательские типы данных определяются с помощью классов. Это позволяет создавать собственные структуры данных с уникальными атрибутами и методами, инкапсулируя логику и состояние.

1. Использование классов: Базовый подход — создание класса, который определяет структуру (атрибуты) и поведение (методы) объекта.

class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

    def distance_to_origin(self) -> float:
        """Вычисляет расстояние от точки до начала координат."""
        return (self.x ** 2 + self.y ** 2) ** 0.5

# Пример использования
p = Point(3, 4)
print(f"Точка: ({p.x}, {p.y}), Расстояние до начала координат: {p.distance_to_origin()}")

2. Использование dataclasses (Python 3.7+): Декоратор @dataclass значительно упрощает создание классов, автоматически генерируя методы, такие как __init__, __repr__, __eq__ и другие, на основе аннотаций типов. Это уменьшает объем шаблонного кода и повышает читаемость.

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float

    def distance_to_origin(self) -> float:
        """Вычисляет расстояние от точки до начала координат."""
        return (self.x ** 2 + self.y ** 2) ** 0.5

# Пример использования
p = Point(3, 4)
print(f"Точка: {p}, Расстояние до начала координат: {p.distance_to_origin()}")

3. Расширенные возможности:

  • Переопределение операторов: Для создания типов, которые ведут себя как встроенные (например, __add__, __eq__), позволяя использовать стандартные операторы Python.
  • typing.NamedTuple: Для создания неизменяемых, легковесных структур данных, которые поддерживают аннотации типов и доступ по имени поля, как у кортежей. Идеально подходит для простых DTO (Data Transfer Objects).
  • Абстрактные базовые классы (ABC): Для определения интерфейсов, которым должны соответствовать подклассы, обеспечивая полиморфизм и стандартизацию поведения.