Типы данных в 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). Подробнее — в гайде по словарям.

Закрепи Python для аналитика
200+ задач по pandas, numpy и работе с данными — с разборами
Тренировать Python в браузере

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 подтип int

isinstance() учитывает наследование и предпочтительнее 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')  # True

Falsy-значения: 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. Больше примеров вопросов — на отдельной странице.

Открыть тренажёр в браузере — вопросы по 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().