Обзор стандартной библиотеки

⏱ 40 мин · 🧩 заданий: 5

Девиз Python — batteries included: многое, за чем в других языках идут в сторонние пакеты, уже есть в стандартной библиотеке. Знать, что там есть, важнее, чем помнить все сигнатуры.

collections

from collections import Counter, defaultdict, deque, OrderedDict, ChainMap

# Counter — подсчёт
votes = Counter(["за", "против", "за", "за", "воздержался"])
print(votes, votes.most_common(1), votes["нет такого"])
print(Counter("hello") + Counter("world"))          # арифметика счётчиков

# defaultdict — значение по умолчанию для нового ключа
by_dept = defaultdict(list)
for name, dept in [("Анна", "IT"), ("Боря", "HR"), ("Вера", "IT")]:
    by_dept[dept].append(name)
print(dict(by_dept))

# deque — двусторонняя очередь: O(1) с обоих концов
q = deque([1, 2, 3], maxlen=4)
q.appendleft(0); q.append(4)                         # 0 вытеснен из-за maxlen
print(q)
q.rotate(1)                                          # сдвиг по кругу вправо
print(q, "→ popleft:", q.popleft(), "→", q)

# ChainMap — поиск по нескольким словарям по очереди
defaults = {"theme": "light", "lang": "ru"}
user = {"theme": "dark"}
settings = ChainMap(user, defaults)
print(settings["theme"], settings["lang"])

# OrderedDict — move_to_end пригодится для LRU-кеша
od = OrderedDict(a=1, b=2, c=3)
od.move_to_end("a")
print(list(od), od.popitem(last=False))

heapq и bisect

import heapq, bisect

tasks = [(3, "почта"), (1, "пожар"), (2, "отчёт")]
heapq.heapify(tasks)                               # минимальная куча за O(n)
heapq.heappush(tasks, (0, "критично"))
print(heapq.heappop(tasks), heapq.heappop(tasks))  # всегда минимальный — O(log n)
print(heapq.nlargest(2, [5, 1, 9, 3, 7]), heapq.nsmallest(2, [5, 1, 9, 3, 7]))

scores = [10, 20, 30, 40]                           # отсортированный список
print(bisect.bisect_left(scores, 25))               # позиция для вставки — двоичный поиск
bisect.insort(scores, 25)
print(scores)
grades = "FDCBA"
print([grades[bisect.bisect([60, 70, 80, 90], s)] for s in [55, 73, 99]])

Подробно кучи и двоичный поиск разберём в модуле алгоритмов.

Числа: math, statistics, decimal, fractions

import math, statistics
from decimal import Decimal, ROUND_HALF_UP
from fractions import Fraction

print(math.sqrt(2), math.isclose(0.1 + 0.2, 0.3), math.gcd(12, 18), math.lcm(4, 6))
print(math.ceil(2.1), math.floor(-2.1), math.comb(5, 2), math.factorial(5), math.inf > 10**100)

data = [2, 4, 4, 4, 5, 5, 7, 9]
print(statistics.mean(data), statistics.median(data), statistics.mode(data), statistics.stdev(data))

print(0.1 + 0.2, Decimal("0.1") + Decimal("0.2"))           # Decimal — точная десятичная арифметика
print(Decimal("2.675").quantize(Decimal("0.01"), rounding=ROUND_HALF_UP), round(2.675, 2))
print(Fraction(1, 3) + Fraction(1, 6))

Деньги — не float

Decimal("0.1") из строки. Decimal(0.1) из float унаследует ошибку двоичного представления. В базах данных для денег — тип NUMERIC/DECIMAL или целые копейки.

random и secrets

import random, secrets

random.seed(42)                                   # воспроизводимость — для тестов и симуляций
print(random.randint(1, 6), random.random(), random.choice("абв"))
cards = list(range(10))
random.shuffle(cards)
print(cards, random.sample(range(100), 3), random.choices("ab", weights=[9, 1], k=5))

print(secrets.token_hex(16))                      # криптостойкие случайные значения
print(secrets.token_urlsafe(16), secrets.randbelow(100))

random предсказуем (вихрь Мерсенна) — для паролей, токенов и ключей только secrets.

Строки и текст

import string, textwrap

print(string.ascii_lowercase, string.digits, string.punctuation)
text = "Python — высокоуровневый язык программирования общего назначения с динамической типизацией."
print(textwrap.fill(text, width=40))
print(textwrap.shorten(text, width=40, placeholder="…"))
print(textwrap.dedent("""
    отступ
      сохраняется относительно
    """).strip())

Идентификаторы, хеши, кодирование

import uuid, hashlib, hmac, base64

print(uuid.uuid4())                               # случайный UUID
print(hashlib.sha256(b"hello").hexdigest()[:32], "...")
print(hashlib.md5(b"hello").hexdigest())         # md5 — только для контрольных сумм, не для паролей!
signature = hmac.new(b"secret-key", b"payload", hashlib.sha256).hexdigest()
print(hmac.compare_digest(signature, signature))  # сравнение без утечки по времени
encoded = base64.b64encode("Привет".encode())
print(encoded, base64.b64decode(encoded).decode())

Пароли хешируют медленными алгоритмами с солью: hashlib.scrypt, bcrypt, argon2 (Django делает это сам).

enum

from enum import Enum, IntEnum, StrEnum, auto, Flag

class Status(StrEnum):
    NEW = auto()
    PAID = auto()
    SHIPPED = auto()

class Perm(Flag):
    READ = auto()
    WRITE = auto()
    DELETE = auto()

print(Status.PAID, Status("new"), Status.PAID == "paid", list(Status))
rights = Perm.READ | Perm.WRITE
print(rights, Perm.WRITE in rights, Perm.DELETE in rights)

Время и замеры

import time, timeit

start = time.perf_counter()                 # для замеров длительности
sum(range(100_000))
print(f"{(time.perf_counter() - start) * 1000:.2f} мс")
print(time.time())                          # Unix-время (секунды с 1970)
print(timeit.timeit("'-'.join(map(str, range(100)))", number=1000))

Работа с системой (вне браузера)

Эти модули работают с ОС, поэтому в браузерной песочнице их показываем без запуска:

import os, sys, shutil, subprocess, argparse
from pathlib import Path

os.environ.get("HOME"); os.getcwd(); os.cpu_count()
sys.argv; sys.exit(1); sys.version

shutil.copy("a.txt", "b.txt"); shutil.rmtree("build"); shutil.which("git")

result = subprocess.run(["git", "status", "--short"], capture_output=True, text=True, check=True)
print(result.stdout)
# никогда не передавайте пользовательский ввод с shell=True — инъекция команд

parser = argparse.ArgumentParser(description="Импорт пользователей")
parser.add_argument("file", type=Path)
parser.add_argument("--dry-run", action="store_true")
parser.add_argument("-n", "--limit", type=int, default=100)
args = parser.parse_args()

Ещё полезное

Модуль Для чего
pathlib, json, csv, datetime, re следующий модуль курса
itertools, functools, operator урок «itertools и functools»
dataclasses, typing, abc, enum ООП и типизация
copy, pprint, reprlib копирование и красивый вывод
logging, traceback, pdb, warnings логирование и отладка
unittest, unittest.mock, doctest тестирование
threading, multiprocessing, concurrent.futures, asyncio конкурентность
sqlite3 встроенная SQL-база
urllib, http.server, socket, email, smtplib сеть
zipfile, tarfile, gzip, tempfile, shutil архивы и файлы
contextlib, weakref, gc, sys, inspect, dis внутренности

Совет для собеседования

Решая задачу, упоминайте подходящие инструменты: «здесь удобен Counter», «для очереди возьму deque, а не список — pop(0) у списка O(n)», «для top-k — heapq.nlargest». Это показывает опыт. Но будьте готовы написать и без них.

Итог

  • collections: Counter, defaultdict, deque, ChainMap, OrderedDict.
  • heapq — куча, bisect — двоичный поиск в отсортированном списке.
  • decimal — для денег, statistics — для статистики, math — математика.
  • random — для симуляций, secrets — для безопасности; uuid, hashlib, hmac, base64.
  • subprocess, argparse, shutil, os, sys — работа с системой и CLI.

Практика решено 0 из 5

Вы не вошли — ответы проверяются, но прогресс не сохранится. Войти или зарегистрироваться.
Задание 1 Программа на Python

Напишите top_words(text, n): вернуть список n самых частых слов текста (в нижнем регистре) в виде пар (слово, количество). Используйте collections.Counter. Слова — последовательности букв (знаки препинания отбросить): re.findall(r"\w+", ...).

Какие тесты проверяют код (3)
assert top_words("Мама мыла раму. Мама, мама!", 1) == [("мама", 3)]
assert top_words("a b b c c c", 2) == [("c", 3), ("b", 2)]
assert top_words("", 3) == []
Задание 2 Программа на Python

Реализуйте RecentHistory(maxlen) — историю последних действий: - add(item) добавляет действие; если их больше maxlen, самое старое вытесняется; - last() возвращает список действий от новых к старым. Используйте collections.deque(maxlen=...).

Какие тесты проверяют код (3)
h = RecentHistory(3); [h.add(x) for x in "abcde"]; assert h.last() == ["e", "d", "c"]
h = RecentHistory(2); assert h.last() == []
from collections import deque; assert isinstance(RecentHistory(1).items, deque)
Задание 3 Программа на Python

Посчитайте сумму денег без ошибок округления: money_sum(amounts) принимает список строк вида "0.10" и возвращает строку суммы с двумя знаками ("0.30"). Используйте decimal.Decimal, округление — «половина вверх» (ROUND_HALF_UP), как в бухгалтерии: "1.015" → "1.02".

Какие тесты проверяют код (4)
assert money_sum(["0.10", "0.20"]) == "0.30"
assert money_sum(["1.005"] * 1000) == "1005.00"
assert money_sum([]) == "0.00"
assert money_sum(["1.015"]) == "1.02" and money_sum(["2.675"]) == "2.68"
Задание 4 Заполнить таблицу

Какой модуль подходит для задачи?

randomsecretsuuidhashlib
Перемешать вопросы теста
Сгенерировать токен сброса пароля
Уникальный идентификатор заказа
Контрольная сумма файла SHA-256
Отметьте ячейку — «+», пустая — «−».
Задание 5 Один вариант ответа

Какую сложность имеют deque.appendleft() и list.insert(0, x)?

Войдите, чтобы отмечать пройденные уроки.