← Назад к вопросам
Можно ли создать свою структуру данных в Python?
1.6 Junior🔥 131 комментариев
#Python Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Можно ли создать свою структуру данных в Python?
Абсолютно да! Python предоставляет множество способов создания собственных структур данных. Это один из самых мощных аспектов языка, позволяющий разработчикам проектировать специализированные решения под конкретные задачи.
Базовые способы создания структур данных
1. Пользовательские классы
Самый прямолинейный способ — создать обычный класс:
class Stack:
"""Простая реализация стека"""
def __init__(self):
self._items = []
def push(self, item):
"""Добавить элемент в стек"""
self._items.append(item)
def pop(self):
"""Извлечь элемент из стека"""
if not self.is_empty():
return self._items.pop()
raise IndexError("Стек пуст")
def is_empty(self):
return len(self._items) == 0
def __len__(self):
return len(self._items)
# Использование
stack = Stack()
stack.push(1)
stack.push(2)
print(stack.pop()) # 2
2. Использование dataclass (Python 3.7+)
Для простых структур данных с меньшим количеством кода:
from dataclasses import dataclass, field
from typing import List, Optional
@dataclass
class Node:
"""Узел связного списка"""
value: int
next: Optional['Node'] = None
@dataclass
class LinkedList:
"""Связный список"""
head: Optional[Node] = None
_length: int = field(default=0, init=False)
def append(self, value: int):
"""Добавить элемент в конец списка"""
if self.head is None:
self.head = Node(value)
else:
current = self.head
while current.next:
current = current.next
current.next = Node(value)
self._length += 1
def __len__(self):
return self._length
def __iter__(self):
current = self.head
while current:
yield current.value
current = current.next
# Использование
linked_list = LinkedList()
linked_list.append(10)
linked_list.append(20)
for val in linked_list:
print(val) # 10, 20
3. Использование NamedTuple
Легкая и типобезопасная структура:
from typing import NamedTuple
class Point(NamedTuple):
x: float
y: float
def distance_from_origin(self) -> float:
return (self.x ** 2 + self.y ** 2) ** 0.5
point = Point(3, 4)
print(point.distance_from_origin()) # 5.0
Сложные структуры данных
4. Бинарное дерево поиска (BST)
from dataclasses import dataclass
from typing import Optional
@dataclass
class TreeNode:
value: int
left: Optional['TreeNode'] = None
right: Optional['TreeNode'] = None
class BinarySearchTree:
def __init__(self):
self.root: Optional[TreeNode] = None
def insert(self, value: int):
"""Вставить значение в BST"""
if self.root is None:
self.root = TreeNode(value)
else:
self._insert_recursive(self.root, value)
def _insert_recursive(self, node: TreeNode, value: int):
if value < node.value:
if node.left is None:
node.left = TreeNode(value)
else:
self._insert_recursive(node.left, value)
else:
if node.right is None:
node.right = TreeNode(value)
else:
self._insert_recursive(node.right, value)
def search(self, value: int) -> bool:
"""Найти значение в дереве"""
return self._search_recursive(self.root, value)
def _search_recursive(self, node: Optional[TreeNode], value: int) -> bool:
if node is None:
return False
if node.value == value:
return True
elif value < node.value:
return self._search_recursive(node.left, value)
else:
return self._search_recursive(node.right, value)
def inorder_traversal(self):
"""Обход дерева в порядке возрастания"""
return list(self._inorder_recursive(self.root))
def _inorder_recursive(self, node: Optional[TreeNode]):
if node:
yield from self._inorder_recursive(node.left)
yield node.value
yield from self._inorder_recursive(node.right)
# Использование
bst = BinarySearchTree()
for val in [50, 30, 70, 20, 40, 60, 80]:
bst.insert(val)
print(bst.inorder_traversal()) # [20, 30, 40, 50, 60, 70, 80]
5. Граф (неориентированный)
from collections import defaultdict
from typing import List, Set
class Graph:
def __init__(self):
self.adjacency_list: dict[int, List[int]] = defaultdict(list)
def add_edge(self, u: int, v: int):
"""Добавить ребро между узлами"""
self.adjacency_list[u].append(v)
self.adjacency_list[v].append(u) # неориентированный граф
def bfs(self, start: int) -> List[int]:
"""Поиск в ширину (BFS)"""
visited: Set[int] = set()
queue = [start]
result = []
while queue:
vertex = queue.pop(0)
if vertex not in visited:
visited.add(vertex)
result.append(vertex)
queue.extend(self.adjacency_list[vertex])
return result
def dfs(self, start: int) -> List[int]:
"""Поиск в глубину (DFS)"""
visited: Set[int] = set()
result = []
def _dfs(vertex: int):
visited.add(vertex)
result.append(vertex)
for neighbor in self.adjacency_list[vertex]:
if neighbor not in visited:
_dfs(neighbor)
_dfs(start)
return result
# Использование
graph = Graph()
for u, v in [(0, 1), (0, 2), (1, 3), (2, 3)]:
graph.add_edge(u, v)
print(f"BFS: {graph.bfs(0)}") # [0, 1, 2, 3]
print(f"DFS: {graph.dfs(0)}") # [0, 1, 3, 2]
6. Приоритетная очередь (Heap)
import heapq
from dataclasses import dataclass
@dataclass
class Task:
priority: int
name: str
def __lt__(self, other):
return self.priority < other.priority
class PriorityQueue:
def __init__(self):
self._heap = []
def enqueue(self, priority: int, name: str):
"""Добавить элемент с приоритетом"""
task = Task(priority, name)
heapq.heappush(self._heap, task)
def dequeue(self) -> Task:
"""Извлечь элемент с минимальным приоритетом"""
if not self._heap:
raise IndexError("Очередь пуста")
return heapq.heappop(self._heap)
def is_empty(self) -> bool:
return len(self._heap) == 0
# Использование
pq = PriorityQueue()
pq.enqueue(3, "низкий приоритет")
pq.enqueue(1, "высокий приоритет")
pq.enqueue(2, "средний приоритет")
while not pq.is_empty():
task = pq.dequeue()
print(f"{task.priority}: {task.name}")
# Выведет: 1: высокий приоритет, 2: средний приоритет, 3: низкий приоритет
Продвинутые техники
7. Использование slots для оптимизации памяти
class OptimizedNode:
__slots__ = ['value', 'next']
def __init__(self, value: int):
self.value = value
self.next = None
slots уменьшает потребление памяти, запрещая создание dict для каждого объекта.
8. Магические методы для кастомного поведения
class CustomList:
def __init__(self, items: list):
self._items = items
def __len__(self):
return len(self._items)
def __getitem__(self, index):
return self._items[index]
def __setitem__(self, index, value):
self._items[index] = value
def __contains__(self, item):
return item in self._items
def __iter__(self):
return iter(self._items)
def __repr__(self):
return f"CustomList({self._items})"
custom_list = CustomList([1, 2, 3])
print(len(custom_list)) # 3
print(custom_list[1]) # 2
print(2 in custom_list) # True
Заключение
Python идеально подходит для создания пользовательских структур данных благодаря:
- Гибкости — можно создавать как простые, так и сложные структуры
- Выразительности — магические методы позволяют сделать код интуитивным
- Производительности — встроенные оптимизации и возможность использования slots
- Типобезопасности — type hints помогают избежать ошибок
- Готовым инструментам — dataclass, NamedTuple, heapq и другие
Создание собственных структур данных — это не только возможность, но и важный навык, позволяющий писать более эффективный и чистый код.