Типы данных в Python — полный гайд для аналитика
Коротко
Python — язык с динамической типизацией: переменная не привязана к типу, тип определяется по значению. Для аналитика это значит удобную работу с данными — не нужно объявлять типы заранее. Но на собеседованиях обязательно спросят про разницу мутабельных и иммутабельных типов, приведение типов и подводные камни.
Числовые типы: int, float, complex
# int — целое число, неограниченная точность
users_count = 4200
big = 10 ** 100 # Python справится
# float — число с плавающей точкой (IEEE 754, 64 бита)
conversion_rate = 0.032
revenue = 1_500_000.50 # подчёркивания для читаемости
# complex — комплексное число (редко нужен аналитику)
z = 3 + 4jАналитику важно помнить: float не всегда точен. 0.1 + 0.2 != 0.3 — классика. Для финансовых расчётов лучше decimal.Decimal.
str — строки
name = 'Карьерник'
query = "SELECT * FROM users WHERE status = 'active'"
# f-строки — основной способ форматирования
metric = 'retention'
print(f'Метрика: {metric}, значение: {0.85:.1%}')
# Метрика: retention, значение: 85.0%
# Многострочная строка
sql = """
SELECT user_id, count(*)
FROM events
GROUP BY 1
"""Строки в Python неизменяемы (immutable). Любая операция вроде .upper() или конкатенации создаёт новый объект.
bool и None
is_active = True
has_premium = False
# bool — подтип int
True + True # 2
sum([True, False, True, True]) # 3 — удобно для подсчёта
# None — отсутствие значения
result = None
if result is None:
print('Нет данных')Сравнение с None всегда через is, не ==. Это частый вопрос на собеседовании.
list — списки
metrics = ['dau', 'wau', 'mau']
metrics.append('retention') # добавить элемент
metrics[0] = 'dau_unique' # изменить по индексу
# List comprehension
squares = [x ** 2 for x in range(5)] # [0, 1, 4, 9, 16]list — мутабельный, упорядоченный, допускает дубликаты. Основная рабочая коллекция для аналитика. Подробнее — в статье про list comprehension.
tuple — кортежи
point = (10, 20)
rgb = (255, 128, 0)
singleton = (42,) # запятая обязательна для одного элемента
x, y = point # распаковкаtuple — неизменяемый. Работает как ключ словаря и элемент множества (если все элементы хешируемы). Быстрее и легче list по памяти. Подробнее — в статье list vs tuple.
dict — словари
user = {'name': 'Анна', 'age': 25, 'city': 'Москва'}
user['role'] = 'analyst' # добавить
user.get('salary', 0) # безопасный доступ
# Dict comprehension
{k: v for k, v in user.items() if v != 0}dict — мутабельный, упорядоченный (с Python 3.7+), ключи уникальны. Поиск по ключу за O(1). Подробнее — в гайде по словарям.
set и frozenset — множества
# set — мутабельное множество
unique_users = {101, 102, 103, 101} # {101, 102, 103}
unique_users.add(104)
# Операции над множествами
a = {'sql', 'python', 'excel'}
b = {'python', 'tableau', 'sql'}
a & b # {'sql', 'python'} — пересечение
a | b # {'sql', 'python', 'excel', 'tableau'} — объединение
a - b # {'excel'} — разность
# frozenset — неизменяемое множество, можно использовать как ключ dict
fs = frozenset([1, 2, 3])set — неупорядоченный, без дубликатов. Быстрая проверка in за O(1). Часто используется для дедупликации и операций пересечения/объединения.
Мутабельность — ключевое понятие
Мутабельность определяет, можно ли изменить объект после создания. Это фундаментальная тема на собеседованиях.
| Тип | Мутабельный | Упорядоченный | Пример |
|---|---|---|---|
| int | Нет | — | 42 |
| float | Нет | — | 3.14 |
| str | Нет | Да | 'hello' |
| bool | Нет | — | True |
| None | Нет | — | None |
| tuple | Нет | Да | (1, 2, 3) |
| frozenset | Нет | Нет | frozenset({1, 2}) |
| list | Да | Да | [1, 2, 3] |
| dict | Да | Да (3.7+) | {'a': 1} |
| set | Да | Нет | {1, 2, 3} |
Иммутабельные типы можно хешировать (использовать как ключ dict или элемент set), если все их элементы тоже хешируемы. Мутабельные — нельзя.
Проверка типа: type() и isinstance()
x = [1, 2, 3]
type(x) # <class 'list'>
type(x) == list # True
isinstance(x, list) # True
isinstance(x, (list, tuple)) # True — проверка нескольких типов
isinstance(True, int) # True — bool подтип intisinstance() учитывает наследование и предпочтительнее type() в продакшн-коде. Но type() удобнее для дебага.
Приведение типов
# str -> int / float
int('42') # 42
float('3.14') # 3.14
# int -> str
str(100) # '100'
# list <-> tuple <-> set
list((1, 2, 3)) # [1, 2, 3]
tuple([1, 2, 3]) # (1, 2, 3)
set([1, 1, 2]) # {1, 2}
# bool приведение
bool(0) # False
bool('') # False
bool([]) # False
bool(None) # False
bool(1) # True
bool('text') # TrueFalsy-значения: 0, 0.0, '', [], (), {}, set(), None, False. Всё остальное — truthy. Часто спрашивают на собеседованиях.
Частые ошибки
Мутабельный аргумент по умолчанию. Самый популярный баг Python на собеседованиях:
# Опасно — один и тот же список между вызовами
def add_metric(name, metrics=[]):
metrics.append(name)
return metrics
add_metric('dau') # ['dau']
add_metric('wau') # ['dau', 'wau'] — сюрприз!
# Правильно
def add_metric(name, metrics=None):
if metrics is None:
metrics = []
metrics.append(name)
return metricsЦелочисленное деление. В Python 3 / всегда возвращает float, // — целочисленное деление:
7 / 2 # 3.5 (float)
7 // 2 # 3 (int)Сравнение float. Из-за IEEE 754 нельзя сравнивать float через ==:
0.1 + 0.2 == 0.3 # False
abs(0.1 + 0.2 - 0.3) < 1e-9 # True — правильный подходСоветы для аналитика
- list — когда порядок важен и коллекция будет меняться (список метрик, результаты запроса)
- tuple — фиксированная структура: координаты, составной ключ, return нескольких значений
- set — дедупликация, проверка вхождения, пересечение аудиторий
- dict — маппинги, конфиги, подсчёт вхождений (Counter)
- Для табличных данных — pandas DataFrame, но под капотом всё те же базовые типы
Вопросы с собеседований
— Какие типы данных есть в Python? — Числовые (int, float, complex), строки (str), логические (bool), None, последовательности (list, tuple), множества (set, frozenset), словари (dict). Плюс bytes и bytearray для бинарных данных.
— Что такое мутабельность? Какие типы мутабельные? — Мутабельность — возможность изменить объект после создания. Мутабельные: list, dict, set. Иммутабельные: int, float, str, tuple, frozenset, bool, None. Иммутабельные можно хешировать и использовать как ключи словаря.
— Чем is отличается от ==?
— == сравнивает значения, is — идентичность (один и тот же объект в памяти). is используют для сравнения с None: if x is None.
— Что будет: [] == False? А bool([])?
— [] == False вернёт False — это разные типы, и прямое сравнение не работает. Но bool([]) вернёт False, потому что пустой список — falsy-значение.
— Почему 0.1 + 0.2 != 0.3?
— Из-за представления float в формате IEEE 754. Десятичные дроби 0.1 и 0.2 не имеют точного двоичного представления, поэтому накапливается погрешность. Для точных вычислений используют decimal.Decimal.
— Какая разница между динамической и статической типизацией?
— В статической (Java, C++) тип переменной задаётся при объявлении и не меняется. В динамической (Python, JS) переменная может ссылаться на объект любого типа. Python — динамически и сильно типизированный: тип не нужно указывать, но '5' + 3 вызовет TypeError.
Потренировать Python-вопросы на практике можно в тренажёре Карьерника. Подробнее про словари, list comprehension и list vs tuple. Больше примеров вопросов — на отдельной странице.
Открыть тренажёр в Telegram — вопросы по Python, pandas, SQL и аналитике. Бесплатно.
FAQ
Сколько типов данных в Python?
Встроенных — около 15 (int, float, complex, str, bool, NoneType, list, tuple, dict, set, frozenset, bytes, bytearray, memoryview, range). На практике аналитик использует 8-10 из них: int, float, str, bool, None, list, tuple, dict, set.
Python — строго или слабо типизированный?
Строго (strongly typed). Python не выполняет неявное приведение между несовместимыми типами: '5' + 3 вызовет TypeError, а не '53' или 8. Но при этом типизация динамическая — тип определяется в рантайме, а не при компиляции.
Зачем нужны type hints, если Python динамический?
Type hints (def func(x: int) -> str:) не влияют на выполнение — Python их игнорирует в рантайме. Но они помогают IDE, линтерам (mypy) и другим разработчикам понять, какие типы ожидаются. В аналитических пайплайнах type hints снижают количество багов.
Как узнать тип переменной?
type(x) возвращает класс объекта. isinstance(x, int) проверяет с учётом наследования. Для дебага используйте type(), для проверок в коде — isinstance().