Какие знаешь встроенные структуры данных в Python?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Встроенные структуры данных в Python
Структуры данных — это фундамент Python программирования. Каждая из них имеет свои характеристики по производительности, использованию памяти и семантике. Data Engineer должен выбирать оптимальную структуру для каждой задачи.
1. List (список)
List — упорядоченная, изменяемая коллекция с возможностью содержать элементы любого типа.
# Создание
my_list = [1, 2, 3, 'hello', 4.5]
empty_list = []
list_from_range = list(range(10))
# Основные операции
my_list.append(5) # O(1) amortized
my_list.insert(1, 'new') # O(n)
my_list.extend([6, 7]) # O(k) где k - размер добавляемого списка
my_list.pop() # O(1) - удаляет последний
my_list.pop(0) # O(n) - удаляет первый
my_list.remove(2) # O(n)
# Производительность
# Доступ по индексу: O(1)
first = my_list[0]
last = my_list[-1]
# Поиск элемента: O(n)
index = my_list.index(3)
# Сложность
print(len(my_list)) # O(1)
print(3 in my_list) # O(n)
# List comprehension
squares = [x**2 for x in range(10) if x % 2 == 0] # [0, 4, 16, 36, 64]
Когда использовать: когда нужна упорядоченная коллекция с возможностью изменения.
2. Tuple (кортеж)
Tuple — упорядоченная, неизменяемая (immutable) коллекция. Быстрее списка из-за оптимизаций.
# Создание
my_tuple = (1, 2, 3, 'hello')
empty_tuple = ()
single_element = (42,) # важна запятая!
tuple_from_list = tuple([1, 2, 3])
# Операции
first = my_tuple[0] # O(1)
length = len(my_tuple) # O(1)
index = my_tuple.index(2) # O(n)
# Как ключи словаря (списки не могут быть ключами)
user_position = {(100, 200): 'home'}
print(user_position[(100, 200)]) # 'home'
# Распаковка
x, y, *rest = (1, 2, 3, 4, 5)
print(x, y, rest) # 1 2 [3, 4, 5]
Когда использовать: когда нужна неизменяемая последовательность, ключи для дictionare/set, или функции возвращают несколько значений.
3. Dictionary (словарь)
Dictionary — неупорядоченное хранилище пар ключ-значение (в Python 3.7+ сохраняет порядок вставки).
# Создание
my_dict = {'name': 'Alice', 'age': 30, 'city': 'Moscow'}
empty_dict = {}
# Из пар
from collections import defaultdict
dict_from_pairs = dict([('a', 1), ('b', 2)])
dict_from_args = dict(name='Bob', age=25)
# Доступ
name = my_dict['name'] # O(1) average
age = my_dict.get('age', 0) # безопаснее, возвращает default
# Изменение
my_dict['age'] = 31 # O(1) average
my_dict.update({'city': 'SPB', 'country': 'Russia'})
# Удаление
del my_dict['city'] # O(1) average
my_dict.pop('age') # O(1) average
# Итерация
for key in my_dict: # только ключи
print(key)
for key, value in my_dict.items():
print(f"{key}: {value}")
# Dictionary comprehension
squares = {x: x**2 for x in range(5)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Когда использовать: для быстрого поиска по ключу, хранения структурированных данных.
4. Set (множество)
Set — неупорядоченная коллекция уникальных элементов. Как математическое множество.
# Создание
my_set = {1, 2, 3, 4, 5}
empty_set = set() # {} создаст пустой dict!
set_from_list = set([1, 2, 2, 3, 3, 4]) # {1, 2, 3, 4}
set_from_string = set('hello') # {'h', 'e', 'l', 'o'}
# Операции
my_set.add(6) # O(1) average
my_set.remove(3) # O(1) average, выбросит исключение если нет
my_set.discard(10) # O(1) average, не выбросит ошибку
my_set.pop() # удаляет произвольный элемент
# Проверка принадлежности
if 3 in my_set: # O(1) average
print("Found")
# Операции множеств
set_a = {1, 2, 3}
set_b = {2, 3, 4}
union = set_a | set_b # {1, 2, 3, 4}
intersection = set_a & set_b # {2, 3}
difference = set_a - set_b # {1}
symmetric_diff = set_a ^ set_b # {1, 4}
# Set comprehension
even_set = {x for x in range(10) if x % 2 == 0} # {0, 2, 4, 6, 8}
Когда использовать: для проверки принадлежности, удаления дубликатов, операций множеств.
5. Collections — специальные структуры
from collections import defaultdict, Counter, OrderedDict, namedtuple, deque
# defaultdict — словарь с дефолтным значением
graph = defaultdict(list)
graph['A'].append('B') # не выбросит KeyError
# Counter — подсчёт элементов
words = ['apple', 'banana', 'apple', 'cherry']
word_count = Counter(words) # Counter({'apple': 2, 'banana': 1, 'cherry': 1})
word_count.most_common(2) # [('apple', 2), ('banana', 1)]
# namedtuple — кортеж с именованными полями
Point = namedtuple('Point', ['x', 'y'])
point = Point(10, 20)
print(point.x, point.y) # 10 20
# deque — двусторонняя очередь (очень быстро добавлять/удалять с обоих концов)
from collections import deque
queue = deque([1, 2, 3])
queue.appendleft(0) # O(1) - добавить в начало
queue.popleft() # O(1) - удалить из начала
queue.append(4) # O(1)
queue.pop() # O(1)
6. Сравнение производительности
| Операция | List | Tuple | Dict | Set |
|---|---|---|---|---|
| Доступ по индексу | O(1) | O(1) | - | - |
| Поиск | O(n) | O(n) | O(1)* | O(1)* |
| Вставка | O(n) | - | O(1)* | - |
| Удаление | O(n) | - | O(1)* | O(1)* |
| Итерация | O(n) | O(n) | O(n) | O(n) |
*Среднее время (average case)
Использование в data engineering
# Пример 1: Batch обработка данных
from collections import deque
def process_batch(data_stream, batch_size=1000):
batch = deque(maxlen=batch_size) # autosized queue
for item in data_stream:
batch.append(item)
if len(batch) == batch_size:
yield list(batch)
batch.clear()
if batch:
yield list(batch)
# Пример 2: Дедупликация больших наборов
from collections import Counter
def remove_duplicates_large(data_stream):
seen = set()
for item in data_stream:
if item not in seen:
seen.add(item)
yield item
# Пример 3: Группировка данных
from collections import defaultdict
def group_by_category(transactions):
groups = defaultdict(list)
for transaction in transactions:
groups[transaction['category']].append(transaction)
return dict(groups)
# Пример 4: Top N элементов
from collections import Counter
import heapq
def get_top_n(data, n=10):
counter = Counter(data)
return counter.most_common(n) # O(n log k) где k = n
Memory usage
import sys
# Размер в памяти
print(sys.getsizeof([])) # ~56 bytes
print(sys.getsizeof(())) # ~40 bytes (меньше благодаря immutability)
print(sys.getsizeof({})) # ~240 bytes
print(sys.getsizeof(set())) # ~200 bytes
# Для больших данных нужно выбирать экономно
# Tuple <- List <- Dict/Set (по затратам памяти)
Best Practices
- Используй list для упорядоченных изменяемых данных
- Используй tuple когда данные не меняются или нужны как ключи
- Используй dict для быстрого поиска по ключу
- Используй set для проверки принадлежности и уникальности
- Для очередей (FIFO) используй deque, не list
- Для подсчёта элементов используй Counter
- List comprehension и set comprehension быстрее циклов
- Понимай сложность операций перед выбором структуры
- Для больших объёмов данных рассмотри numpy arrays или pandas DataFrame