Какие знаешь мутабельные структуры данных?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Мутабельные структуры данных в Python
Мутабельные (изменяемые) структуры данных — это те, которые можно модифицировать после создания. Это основные типы в Python.
1. List (Список)
Это самая универсальная мутабельная структура. Хранит элементы в порядке:
# Создание
my_list = [1, 2, 3, 'string', 3.14]
# Добавление
my_list.append(4) # [1, 2, 3, 'string', 3.14, 4]
my_list.extend([5, 6]) # Добавляет несколько элементов
my_list.insert(0, 0) # Вставляет в позицию 0
# Удаление
my_list.remove(2) # Удаляет первое вхождение значения 2
my_list.pop() # Удаляет и возвращает последний элемент
my_list.pop(0) # Удаляет и возвращает элемент по индексу
my_list.clear() # Очищает список
# Изменение
my_list[0] = 100 # Присваивает новое значение
my_list[1:3] = [10, 20] # Срез
# Сортировка (изменяет список на месте)
my_list.sort() # Сортирует по умолчанию
my_list.sort(reverse=True) # Сортирует в обратном порядке
my_list.reverse() # Разворачивает список
Сложность:
- Append: O(1) амортизированная
- Insert в конец: O(1)
- Insert в середину: O(n)
- Pop с конца: O(1)
- Pop с начала: O(n)
2. Dictionary (Словарь)
Хранит пары ключ-значение. Очень быстрый поиск:
# Создание
my_dict = {'name': 'John', 'age': 30, 'city': 'NYC'}
my_dict = dict(name='John', age=30)
# Добавление
my_dict['email'] = 'john@example.com' # Новый ключ
my_dict.setdefault('phone', '+1-555-0123') # Добавляет если не существует
# Обновление
my_dict['age'] = 31 # Изменяет значение
my_dict.update({'age': 31, 'country': 'USA'}) # Обновляет несколько
# Удаление
del my_dict['email'] # Удаляет по ключу
value = my_dict.pop('phone') # Удаляет и возвращает значение
my_dict.clear() # Очищает словарь
# Проверка
if 'name' in my_dict:
print(my_dict['name'])
# Получение с default
value = my_dict.get('phone', '+1-999-9999') # Возвращает default если нет
Сложность:
- Get/Set/Delete: O(1) в среднем случае
- Collision handling: O(n) в худшем
3. Set (Множество)
Хранит уникальные элементы без порядка. Очень быстрая проверка наличия:
# Создание
my_set = {1, 2, 3, 4, 5}
my_set = set([1, 2, 2, 3]) # {1, 2, 3} — дубликаты удалены
empty_set = set() # {} — пустой словарь, нужен set()
# Добавление
my_set.add(6) # Добавляет один элемент
my_set.update([7, 8, 9]) # Добавляет несколько
# Удаление
my_set.remove(5) # Ошибка если не существует
my_set.discard(5) # Без ошибки
value = my_set.pop() # Удаляет и возвращает произвольный элемент
my_set.clear() # Очищает
# Операции над множествами
set1 = {1, 2, 3}
set2 = {3, 4, 5}
intersection = set1 & set2 # {3} — пересечение
union = set1 | set2 # {1, 2, 3, 4, 5} — объединение
difference = set1 - set2 # {1, 2} — разность
sym_diff = set1 ^ set2 # {1, 2, 4, 5} — симметрическая разность
Сложность:
- Add/Remove/Contains: O(1) в среднем
- Intersection/Union: O(len(s1) + len(s2))
4. Bytearray
Изменяемый аналог bytes для работы с бинарными данными:
# Создание
my_bytearray = bytearray(b'hello')
my_bytearray = bytearray(5) # [0, 0, 0, 0, 0]
# Изменение
my_bytearray[0] = 72 # my_bytearray[0] = 'H'
my_bytearray[1:3] = b'EL' # Замена диапазона
# Добавление
my_bytearray.append(33) # Добавляет один байт
my_bytearray.extend(b' world') # Добавляет несколько
# Удаление
del my_bytearray[0] # Удаляет байт по индексу
my_bytearray.pop() # Удаляет и возвращает последний
5. Deque (Double-ended queue)
Оптимизирована для добавления/удаления с обоих концов:
from collections import deque
# Создание
my_deque = deque([1, 2, 3, 4, 5])
my_deque = deque(maxlen=3) # Максимум 3 элемента, старые удаляются
# Добавление
my_deque.append(6) # Добавляет в конец
my_deque.appendleft(0) # Добавляет в начало
my_deque.extend([7, 8]) # Добавляет несколько в конец
my_deque.extendleft([0, -1]) # Добавляет в начало
# Удаление
value = my_deque.pop() # Удаляет с конца
value = my_deque.popleft() # Удаляет с начала
my_deque.remove(3) # Удаляет первое вхождение значения
my_deque.clear() # Очищает
# Ротация
my_deque.rotate(1) # Вращает на 1 позицию вправо
my_deque.rotate(-1) # Вращает на 1 позицию влево
Сложность:
- Append/Pop с концов: O(1)
- Append/Pop с середины: O(n)
6. Counter (Счётчик)
Специализированный словарь для подсчёта элементов:
from collections import Counter
# Создание
my_counter = Counter('abracadabra')
# Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
my_counter = Counter(['apple', 'banana', 'apple', 'cherry'])
# Counter({'apple': 2, 'banana': 1, 'cherry': 1})
# Добавление
my_counter['apple'] += 1
my_counter.update(['apple', 'banana']) # Увеличивает счётчики
# Удаление
my_counter.subtract(['apple']) # Уменьшает счётчики
my_counter['unknown'] # Возвращает 0 если нет
# Самые частые
my_counter.most_common(2) # [(элемент, количество), ...]
# Операции
sum(my_counter.values()) # Общее количество элементов
7. DefaultDict
Словарь с default значением для новых ключей:
from collections import defaultdict
# Создание с default list
my_dict = defaultdict(list)
my_dict['colors'].append('red')
my_dict['colors'].append('blue')
# {'colors': ['red', 'blue']}
# Создание с default int
my_dict = defaultdict(int)
my_dict['a'] += 1
# {'a': 1}
# Кастомная функция default
my_dict = defaultdict(lambda: 'unknown')
my_dict['key'] # 'unknown'
8. ChainMap
Комбинирует несколько словарей:
from collections import ChainMap
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
chain = ChainMap(dict1, dict2)
chain['a'] # 1 (из dict1)
chain['c'] # 3 (из dict2)
chain['x'] = 10 # Добавляет в первый словарь (dict1)
Сравнение и выбор структуры
# Если нужен упорядоченный список с быстрым доступом
data = [1, 2, 3, 4, 5] # List
# Если нужно хранить пары ключ-значение
user = {'name': 'John', 'age': 30} # Dict
# Если нужно хранить уникальные элементы
tags = {'python', 'django', 'fastapi'} # Set
# Если нужно работать с обоими концами
queue = deque([1, 2, 3]) # Deque
# Если нужно подсчитать элементы
freq = Counter('aaabbc') # Counter
# Если нужно кластеризировать данные
groups = defaultdict(list) # DefaultDict
Изменяемость vs Неизменяемость
# Мутабельные (изменяемые)
mutable = [1, 2, 3]
mutable[0] = 100 # OK
# Иммутабельные (неизменяемые)
immutable = (1, 2, 3)
immutable[0] = 100 # TypeError!
# Мутабельные объекты опасны как ключи словарей
my_dict = {(1, 2): 'tuple'} # OK
my_dict[[1, 2]] = 'list' # TypeError! List не может быть ключом
Best Practices
1. Используй правильную структуру
- List — если нужен порядок
- Set — если нужна скорость проверки
- Dict — если нужны ключ-значение
2. Будь осторожен с передачей
# ОПАСНО: изменение влияет на исходный список
def modify_list(lst):
lst[0] = 100
original = [1, 2, 3]
modify_list(original) # original изменена!
# БЕЗОПАСНО: копирование
def modify_list(lst):
lst = lst.copy() # Или lst[:]
lst[0] = 100 # Не влияет на исходный
3. Понимай сложность операций
- List.insert(0, x) — O(n), медленно!
- Deque.appendleft(x) — O(1), быстро
Мутабельные структуры — основа Python, выбирай правильно для каждой задачи.