Подробное пособие по основам Python

Изучайте Python с нуля с понятными примерами и упражнениями

Глава 1: Введение в Python

Python — это высокоуровневый язык программирования общего назначения, который отличается простым синтаксисом и мощными возможностями.

1.1 Установка Python

Для начала работы с Python необходимо установить интерпретатор:

  1. Скачайте Python с официального сайта
  2. Запустите установщик
  3. Убедитесь, что отмечена галочка "Add Python to PATH"
  4. Завершите установку
Проверка установки: Откройте командную строку и введите python --version. Вы должны увидеть версию Python.

1.2 Первая программа

Традиционно первая программа на любом языке — это "Hello, World!". В Python это делается одной строкой:

print("Hello, World!")

Упражнение 1.1

Напишите программу, которая выводит ваше имя и возраст, используя функцию print(). Например:

Меня зовут Иван, мне 25 лет.

Глава 2: Переменные и типы данных

Переменные в Python используются для хранения данных. В отличие от других языков, в Python не нужно явно объявлять тип переменной.

2.1 Основные типы данных

Тип Описание Пример
int Целое число 42, -10, 0
float Число с плавающей точкой 3.14, -0.001, 2.0
str Строка (текст) "hello", 'Python', "42"
bool Логический тип True, False
list Список [1, 2, 3], ["a", "b", "c"]
dict Словарь {"name": "John", "age": 30}

2.2 Работа с переменными

# Объявление переменных
name = "Алексей" # строка
age = 25 # целое число
height = 1.75 # число с плавающей точкой
is_student = True # логическое значение

# Вывод значений переменных
print("Имя:", name)
print("Возраст:", age)
print("Рост:", height)
print("Студент:", is_student)

# Динамическая типизация
variable = 10
print("Тип переменной:", type(variable)) # <class 'int'>

variable = "Теперь я строка"
print("Тип переменной:", type(variable)) # <class 'str'>
Важно: Имена переменных в Python чувствительны к регистру. Переменные name, Name и NAME — это три разные переменные.

Упражнение 2.1

Создайте программу, которая:

  1. Создает переменные для хранения вашего имени, возраста и любимого цвета
  2. Выводит эти значения в формате: "Меня зовут [имя], мне [возраст] лет, мой любимый цвет — [цвет]"
  3. Добавляет год к возрасту и выводит обновленное сообщение

Глава 3: Операторы и выражения

Операторы позволяют выполнять различные операции с переменными и значениями.

3.1 Арифметические операторы

Оператор Описание Пример
+ Сложение 5 + 3 → 8
- Вычитание 5 - 3 → 2
* Умножение 5 * 3 → 15
/ Деление 5 / 2 → 2.5
// Целочисленное деление 5 // 2 → 2
% Остаток от деления 5 % 2 → 1
** Возведение в степень 5 ** 2 → 25
# Примеры арифметических операций
a = 10
b = 3

print(a + b) # 13
print(a - b) # 7
print(a * b) # 30
print(a / b) # 3.333...
print(a // b) # 3
print(a % b) # 1
print(a ** b) # 1000

3.2 Операторы сравнения

Оператор Описание Пример
== Равно 5 == 5 → True
!= Не равно 5 != 3 → True
> Больше 5 > 3 → True
< Меньше 5 < 3 → False
>= Больше или равно 5 >= 5 → True
<= Меньше или равно 5 <= 3 → False
# Примеры операторов сравнения
x = 5
y = 7

print(x == y) # False
print(x != y) # True
print(x > y) # False
print(x < y) # True
print(x >= 5) # True
print(y <= 7) # True

Упражнение 3.1

Напишите программу, которая:

  1. Запрашивает у пользователя два числа (используйте функцию input())
  2. Выводит результаты всех арифметических операций с этими числами
  3. Сравнивает числа и выводит, какое из них больше или равны ли они

Глава 4: Условные операторы

Условные операторы позволяют выполнять разные действия в зависимости от условий.

4.1 Оператор if

# Простая условная конструкция
age = 18

if age >= 18:
    print("Вы совершеннолетний")
else:
    print("Вы несовершеннолетний")

4.2 Оператор elif

# Множественные условия
score = 85

if score >= 90:
    print("Отлично! Оценка A")
elif score >= 80:
    print("Хорошо! Оценка B")
elif score >= 70:
    print("Удовлетворительно! Оценка C")
elif score >= 60:
    print("Оценка D")
else:
    print("Неудовлетворительно! Оценка F")
Обратите внимание: В Python важны отступы! Код внутри блока if/else должен иметь отступ (обычно 4 пробела или табуляция).

Упражнение 4.1

Напишите программу, которая:

  1. Запрашивает у пользователя температуру в градусах Цельсия
  2. Если температура ниже 0, выводит "Холодно, на улице мороз!"
  3. Если от 0 до 15: "Прохладно, одевайтесь теплее"
  4. От 16 до 25: "Тепло и комфортно"
  5. Выше 25: "Жарко, можно идти купаться!"

Глава 5: Циклы

Циклы позволяют выполнять один и тот же блок кода несколько раз.

5.1 Цикл for

# Вывод чисел от 1 до 5
for i in range(1, 6):
    print(i)

# Перебор элементов списка
fruits = ["яблоко", "банан", "вишня"]
for fruit in fruits:
    print(fruit)

# Цикл с шагом 2
for i in range(0, 10, 2):
    print(i) # 0, 2, 4, 6, 8

5.2 Цикл while

# Счетчик
count = 0
while count < 5:
    print(count)
    count += 1 # Эквивалентно count = count + 1

# Бесконечный цикл с break
while True:
    user_input = input("Введите 'выход' для завершения: ")
    if user_input.lower() == 'выход':
        break
    print(f"Вы ввели: {user_input}")

Упражнение 5.1

Напишите программу, которая:

  1. Запрашивает у пользователя число N
  2. Выводит таблицу умножения для этого числа от 1 до 10
  3. Используйте цикл for для решения

Пример вывода для N=5:

5 * 1 = 5
5 * 2 = 10
...
5 * 10 = 50

Глава 6: Функции

Функции позволяют организовать код в повторно используемые блоки.

6.1 Определение функций

# Простая функция без параметров
def greet():
    print("Привет, мир!")

# Вызов функции
greet() # Выведет: Привет, мир!

# Функция с параметрами
def greet_person(name):
    print(f"Привет, {name}!")

greet_person("Анна") # Выведет: Привет, Анна!
greet_person("Петр") # Выведет: Привет, Петр!

6.2 Возвращение значений

# Функция с возвращаемым значением
def add_numbers(a, b):
    return a + b

result = add_numbers(5, 3)
print(result) # Выведет: 8

# Функция может возвращать несколько значений (кортеж)
def calculate(a, b):
    return a + b, a - b, a * b

sum_result, diff_result, prod_result = calculate(10, 5)
print(sum_result, diff_result, prod_result) # 15 5 50
Совет: Имена функций должны быть описательными и следовать стилю snake_case (все слова в нижнем регистре с подчеркиваниями).

Упражнение 6.1

Создайте функцию calculate_circle, которая:

  1. Принимает радиус круга в качестве параметра
  2. Возвращает площадь и длину окружности (используйте формулу площади πr² и длины 2πr)
  3. Для значения π используйте 3.14159
  4. Вызовите функцию с разными значениями радиуса и выведите результаты

Глава 7: Списки

Списки — это упорядоченные изменяемые коллекции объектов.

7.1 Основы работы со списками

# Создание списка
numbers = [1, 2, 3, 4, 5]
fruits = ["яблоко", "банан", "вишня"]
mixed = [1, "текст", True, 3.14]

# Обращение к элементам
print(fruits[0]) # яблоко (индексы начинаются с 0)
print(fruits[-1]) # вишня (отрицательные индексы - с конца)

# Изменение элементов
fruits[1] = "киви"
print(fruits) # ['яблоко', 'киви', 'вишня']

# Длина списка
print(len(numbers)) # 5

7.2 Методы списков

Метод Описание Пример
append() Добавляет элемент в конец fruits.append("апельсин")
insert() Вставляет элемент по индексу fruits.insert(1, "лимон")
remove() Удаляет первый найденный элемент fruits.remove("банан")
pop() Удаляет и возвращает элемент по индексу fruits.pop(2)
sort() Сортирует список numbers.sort()
reverse() Разворачивает список fruits.reverse()
# Примеры методов списков
colors = ["красный", "синий", "зеленый"]

colors.append("желтый")
print(colors) # ['красный', 'синий', 'зеленый', 'желтый']

colors.insert(1, "оранжевый")
print(colors) # ['красный', 'оранжевый', 'синий', 'зеленый', 'желтый']

colors.remove("синий")
print(colors) # ['красный', 'оранжевый', 'зеленый', 'желтый']

last_color = colors.pop()
print(last_color) # желтый
print(colors) # ['красный', 'оранжевый', 'зеленый']

colors.sort()
print(colors) # ['зеленый', 'красный', 'оранжевый']

colors.reverse()
print(colors) # ['оранжевый', 'красный', 'зеленый']

Упражнение 7.1

Создайте программу для управления списком задач:

  1. Создайте пустой список tasks
  2. Добавьте функции для добавления, удаления и просмотра задач
  3. Реализуйте меню с выбором действий (1 - добавить, 2 - удалить, 3 - показать все, 4 - выход)
  4. Используйте цикл while для работы программы, пока пользователь не выберет выход

Глава 8: Словари

Словари хранят данные в виде пар ключ-значение.

8.1 Основы работы со словарями

# Создание словаря
student = {
    "имя": "Алексей",
    "возраст": 20,
    "курс": 3,
    "предметы": ["Математика", "Программирование"]
}

# Доступ к значениям
print(student["имя"]) # Алексей
print(student.get("возраст")) # 20

# Изменение значений
student["возраст"] = 21
student["курс"] += 1
print(student) # {'имя': 'Алексей', 'возраст': 21, 'курс': 4, ...}

# Добавление новых пар
student["стипендия"] = True
print(student) # Добавится 'стипендия': True

8.2 Методы словарей

Метод Описание Пример
keys() Возвращает ключи student.keys()
values() Возвращает значения student.values()
items() Возвращает пары ключ-значение student.items()
get() Безопасное получение значения student.get("имя")
pop() Удаляет и возвращает значение по ключу student.pop("возраст")
update() Обновляет словарь student.update({"город": "Москва"})
# Примеры методов словарей
car = {
    "марка": "Toyota",
    "модель": "Camry",
    "год": 2020
}

# Получение всех ключей
print(car.keys()) # dict_keys(['марка', 'модель', 'год'])

# Получение всех значений
print(car.values()) # dict_values(['Toyota', 'Camry', 2020])

# Получение пар ключ-значение
print(car.items()) # dict_items([('марка', 'Toyota'), ('модель', 'Camry'), ('год', 2020)])

# Безопасное получение значения
print(car.get("цвет", "не указан")) # не указан

# Обновление словаря
car.update({"цвет": "серебристый", "пробег": 15000})
print(car) # {'марка': 'Toyota', 'модель': 'Camry', 'год': 2020, 'цвет': 'серебристый', 'пробег': 15000}

Упражнение 8.1

Создайте программу "Телефонная книга":

  1. Создайте словарь для хранения контактов (имя → телефон)
  2. Реализуйте функции для добавления, поиска, удаления и вывода всех контактов
  3. Сделайте меню с выбором действий
  4. Используйте цикл while для работы программы до выбора выхода

Глава 9: Работа с файлами

Python предоставляет удобные средства для работы с файлами.

9.1 Чтение и запись файлов

# Запись в файл
with open("example.txt", "w") as file:
    file.write("Привет, мир!\n")
    file.write("Это пример записи в файл.\n")

# Чтение файла целиком
with open("example.txt", "r") as file:
    content = file.read()
    print(content)

# Чтение файла построчно
with open("example.txt", "r") as file:
    for line in file:
        print(line.strip()) # strip() удаляет лишние пробелы и переносы

9.2 Режимы работы с файлами

Режим Описание
"r" Чтение (по умолчанию)
"w" Запись (перезаписывает файл)
"a" Добавление в конец файла
"r+" Чтение и запись
"b" Бинарный режим (например, "rb" или "wb")
# Добавление в файл
with open("example.txt", "a") as file:
    file.write("Новая строка добавлена в конец.\n")

# Чтение и запись одновременно
with open("example.txt", "r+") as file:
    content = file.read()
    file.seek(0) # Перемещаем курсор в начало файла
    file.write("Первая строка (измененная)\n" + content)

Упражнение 9.1

Создайте программу для ведения дневника:

  1. При запуске программа должна запрашивать у пользователя текст записи
  2. Записи должны сохраняться в файл с текущей датой в имени (например, "2023-11-15.txt")
  3. Каждая новая запись должна добавляться в файл с указанием времени
  4. Реализуйте возможность просмотра всех записей за выбранную дату

Для работы с датами используйте модуль datetime:

from datetime import datetime
today = datetime.now().strftime("%Y-%m-%d")
time_now = datetime.now().strftime("%H:%M")

Глава 10: Обработка исключений

Исключения позволяют обрабатывать ошибки и нештатные ситуации.

10.1 Блоки try-except

# Обработка деления на ноль
try:
    result = 10 / 0
except ZeroDivisionError:
    print("Ошибка: деление на ноль!")

# Обработка нескольких исключений
try:
    number = int(input("Введите число: "))
    print(f"Вы ввели: {number}")
except ValueError:
    print("Это не число!")
except Exception as e:
    print(f"Произошла ошибка: {e}")

10.2 Блоки else и finally

# Блок else выполняется, если исключений не было
try:
    age = int(input("Введите ваш возраст: "))
except ValueError:
    print("Некорректный ввод!")
else:
    print(f"Вам {age} лет")

# Блок finally выполняется всегда
try:
    file = open("example.txt", "r")
    content = file.read()
    print(content)
except FileNotFoundError:
    print("Файл не найден!")
finally:
    if 'file' in locals(): # Проверяем, был ли создан объект file
        file.close()
    print("Операция завершена")

Упражнение 10.1

Модифицируйте программу "Телефонная книга" из главы 8:

  1. Добавьте сохранение контактов в файл при выходе
  2. Добавьте загрузку контактов из файла при запуске
  3. Реализуйте обработку исключений для случаев, когда файл не существует или поврежден
  4. Добавьте подтверждение при удалении контакта

Глава 11: Классы и объектно-ориентированное программирование

ООП позволяет организовывать код в виде объектов, объединяющих данные и функциональность.

11.1 Создание классов и объектов

# Простой класс
class Dog:
    # Метод __init__ вызывается при создании объекта
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def bark(self):
        print(f"{self}.name говорит: Гав!")

# Создание объектов
dog1 = Dog("Бобик", 3)
dog2 = Dog("Шарик", 5)

print(dog1.name) # Бобик
dog2.bark() # Шарик говорит: Гав!

11.2 Наследование и полиморфизм

# Базовый класс
class Animal:
    def __init__(self, name):
        self.name = name

    def make_sound(self):
        print("Звук животного")

# Дочерний класс
class Cat(Animal):
    def make_sound(self):
        print("Мяу!")

# Еще один дочерний класс
class Bird(Animal):
    def make_sound(self):
        print("Чирик!")

# Использование полиморфизма
animals = [Cat("Мурзик"), Bird("Кеша")]
for animal in animals:
    animal.make_sound() # Мяу! Чирик!

Упражнение 11.1

Создайте систему классов для представления геометрических фигур:

  1. Базовый класс Shape с методами area() и perimeter()
  2. Классы Circle, Rectangle и Triangle, наследующие от Shape
  3. Реализуйте расчет площади и периметра для каждой фигуры
  4. Создайте список фигур и выведите информацию о каждой

Глава 12: Модули и пакеты

Модули позволяют организовывать код в отдельные файлы, а пакеты — в каталоги.

12.1 Создание и использование модулей

# Файл geometry.py (отдельный модуль)
"""Модуль для геометрических вычислений"""
def circle_area(radius):
    return 3.14159 * radius ** 2

def rectangle_area(length, width):
    return length * width

# Файл main.py (основная программа)
import geometry

print(geometry.circle_area(5))
print(geometry.rectangle_area(4, 7))

# Импорт с псевдонимом
import geometry as geo
print(geo.circle_area(3))

# Импорт конкретных функций
from geometry import rectangle_area
print(rectangle_area(2, 9))

12.2 Стандартные модули Python

# Модуль math
import math

print(math.sqrt(16)) # 4.0
print(math.pi) # 3.141592653589793
print(math.factorial(5)) # 120

# Модуль random
import random

print(random.random()) # Случайное число от 0 до 1
print(random.randint(1, 10)) # Случайное целое от 1 до 10
print(random.choice(['a', 'b', 'c'])) # Случайный элемент списка

# Модуль datetime
from datetime import datetime, timedelta

now = datetime.now()
print(now.strftime("%Y-%m-%d %H:%M:%S")) # Текущая дата и время
tomorrow = now + timedelta(days=1)
print(tomorrow) # Дата завтра

Упражнение 12.1

Создайте пакет для работы с банковским счетом:

  1. Создайте папку bank с файлом __init__.py
  2. В модуле account.py реализуйте класс BankAccount
  3. В модуле transactions.py добавьте функции для операций
  4. В модуле utils.py добавьте вспомогательные функции
  5. Создайте основную программу, которая импортирует и использует этот пакет

Глава 13: Работа с JSON

JSON — популярный формат для хранения и передачи структурированных данных.

13.1 Чтение и запись JSON

# Преобразование Python-объектов в JSON
import json

data = {
    "имя": "Иван",
    "возраст": 30,
    "город": "Москва",
    "хобби": ["чтение", "программирование"]
}

# Преобразование в JSON-строку
json_string = json.dumps(data, ensure_ascii=False, indent=4)
print(json_string)

# Запись JSON в файл
with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=4)

# Чтение JSON из файла
with open("data.json", "r", encoding="utf-8") as f:
    loaded_data = json.load(f)
print(loaded_data["имя"]) # Иван

13.2 Работа с API

# Пример работы с API с использованием модуля requests
import requests
import json

# Получение данных с открытого API
response = requests.get("https://api.github.com/users/python")
if response.status_code == 200:
    user_data = response.json()
    print(f"Имя: {user_data['name']}")
    print(f"Репозитории: {user_data['public_repos']}")
else:
    print(f"Ошибка: {response.status_code}")

# Отправка POST-запроса с JSON
new_data = {"title": "Пример", "body": "Содержание", "userId": 1}
response = requests.post("https://jsonplaceholder.typicode.com/posts", json=new_data)
print(response.json()) # Вывод ответа сервера

Упражнение 13.1

Создайте программу для работы с погодными данными:

  1. Используйте API OpenWeatherMap (или другой бесплатный API погоды)
  2. Запрашивайте у пользователя название города
  3. Получайте текущую погоду для этого города
  4. Сохраняйте историю запросов в JSON-файл
  5. Добавьте возможность просмотра истории запросов

Глава 14: Декораторы

Декораторы позволяют модифицировать поведение функций без изменения их кода.

14.1 Создание и применение декораторов

# Простой декоратор
def my_decorator(func):
    def wrapper():
        print("Действие до вызова функции")
        func()
        print("Действие после вызова функции")
    return wrapper

@my_decorator
def say_hello():
    print("Привет!")

say_hello()
# Вывод:
# Действие до вызова функции
# Привет!
# Действие после вызова функции

14.2 Полезные примеры декораторов

# Декоратор для измерения времени выполнения
import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"Функция {func.__name__} выполнилась за {end-start:.4f} секунд")
        return result
    return wrapper

@timer
def long_running_function(n):
    sum = 0
    for i in range(n):
        sum += i
    return sum

long_running_function(1000000)

# Декоратор для кэширования результатов
def cache(func):
    cached_results = {}
    def wrapper(*args):
        if args in cached_results:
            print("Возвращаем кэшированный результат")
            return cached_results[args]
        result = func(*args)
        cached_results[args] = result
        print("Вычисляем и кэшируем результат")
        return result
    return wrapper

@cache
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10)) # Без декоратора будет очень медленно

Упражнение 14.1

Создайте несколько полезных декораторов:

  1. Декоратор для логирования (записывает в файл время вызова, аргументы и результат)
  2. Декоратор для проверки авторизации (имитирует проверку прав доступа)
  3. Декоратор для повторного выполнения функции при ошибке (с заданным количеством попыток)
  4. Примените эти декораторы к различным функциям

Глава 15: Работа с базами данных

Python предоставляет удобные интерфейсы для работы с различными СУБД.

15.1 SQLite - встроенная база данных

# Работа с SQLite
import sqlite3

# Создание и подключение к базе данных
conn = sqlite3.connect("example.db")
cursor = conn.cursor()

# Создание таблицы
cursor.execute("""CREATE TABLE IF NOT EXISTS users
(id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE,
age INTEGER)"""
)

# Вставка данных
cursor.execute("INSERT INTO users (name, email, age) VALUES (?, ?, ?)",
("Иван Иванов", "ivan@example.com", 30))
conn.commit() # Сохранение изменений

# Чтение данных
cursor.execute("SELECT * FROM users")
rows = cursor.fetchall()
for row in rows:
    print(row)

# Закрытие соединения
conn.close()

15.2 SQLAlchemy - ORM для Python

# Работа с ORM SQLAlchemy
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# Определение модели
Base = declarative_base()

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    email = Column(String, unique=True)
    age = Column(Integer)

    def __repr__(self):
        return f"<User(name='{self}.name', email='{self}.email')>"

# Создание движка и сессии
engine = create_engine('sqlite:///example_orm.db')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

# Добавление нового пользователя
new_user = User(name="Петр Петров", email="petr@example.com", age=25)
session.add(new_user)
session.commit()

# Запрос данных
users = session.query(User).filter(User.age > 20).all()
print(users) # Вывод всех пользователей старше 20 лет

# Закрытие сессии
session.close()

Упражнение 15.1

Создайте систему управления библиотекой:

  1. Создайте модели для книг, авторов и читателей
  2. Реализуйте функции для добавления, поиска и "выдачи" книг
  3. Добавьте возможность просмотра всех книг определенного автора
  4. Реализуйте поиск книг по названию или жанру
  5. Используйте либо SQLite напрямую, либо ORM SQLAlchemy

Глава 16: Асинхронное программирование

Asyncio позволяет писать конкурентный код, используя синтаксис async/await.

16.1 Основы async/await

import asyncio

async def fetch_data():
    print("Начало загрузки данных")
    await asyncio.sleep(2) # Имитация долгой операции
    print("Данные загружены")
    return "результат"

async def main():
    task = asyncio.create_task(fetch_data())
    print("Делаем другие дела во время загрузки...")
    result = await task
    print(f"Полученный результат: {result}")

asyncio.run(main())

16.2 Асинхронные HTTP-запросы

import aiohttp
import asyncio

async def fetch_url(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()

async def main():
    urls = [
        "https://python.org",
        "https://github.com",
        "https://stackoverflow.com"
    ]
    tasks = [fetch_url(url) for url in urls]
    results = await asyncio.gather(*tasks)
    for url, content in zip(urls, results):
        print(f"{url}: {len(content)} символов")

asyncio.run(main())

Упражнение 16.1

Создайте асинхронный веб-сканер:

  1. Считывает список URL из файла
  2. Асинхронно загружает содержимое каждого сайта
  3. Сохраняет результаты в отдельные файлы
  4. Выводит статистику (размер, время загрузки)

Глава 17: Тестирование кода

Правильное тестирование - залог надежного кода.

17.1 Модуль unittest

import unittest

def add(a, b):
    return a + b

class TestMathOperations(unittest.TestCase):
    def test_add_positive_numbers(self):
        self.assertEqual(add(2, 3), 5)

    def test_add_negative_numbers(self):
        self.assertEqual(add(-1, -1), -2)

    def test_add_zero(self):
        self.assertEqual(add(0, 0), 0)

    def test_add_type_error(self):
        with self.assertRaises(TypeError):
            add("2", 3)

if __name__ == '__main__':
    unittest.main()

17.2 Pytest - современный подход

# Файл test_operations.py
import pytest

def divide(a, b):
    if b == 0:
        raise ValueError("Нельзя делить на ноль")
    return a / b

def test_divide_normal():
    assert divide(10, 2) == 5

def test_divide_float_result():
    assert divide(5, 2) == 2.5

def test_divide_by_zero():
    with pytest.raises(ValueError, match="Нельзя делить на ноль"):
        divide(10, 0)

# Фикстуры
@pytest.fixture
def sample_data():
    return [1, 2, 3, 4, 5]

def test_sum(sample_data):
    assert sum(sample_data) == 15

Упражнение 17.1

Напишите тесты для класса Calculator:

  1. Создайте класс Calculator с методами add, subtract, multiply, divide
  2. Напишите unit-тесты для всех методов
  3. Покройте все граничные случаи
  4. Добавьте параметризованные тесты с @pytest.mark.parametrize

Глава 18: Виртуальные окружения и управление зависимостями

Изоляция проектов и управление пакетами - важные навыки разработчика.

18.1 Создание и использование venv

# Создание виртуального окружения
python -m venv myenv

# Активация на Windows
myenv\Scripts\activate

# Активация на Linux/Mac
source myenv/bin/activate

# Установка пакетов в активированном окружении
pip install requests pandas numpy

# Заморозка зависимостей
pip freeze > requirements.txt

# Установка из requirements.txt
pip install -r requirements.txt

18.2 Poetry - современный менеджер зависимостей

# Инициализация проекта
poetry new myproject
cd myproject

# Добавление зависимостей
poetry add requests pandas
poetry add --dev pytest

# Запуск скриптов
poetry run python myscript.py

# Обновление зависимостей
poetry update

# Экспорт requirements.txt
poetry export -f requirements.txt --output requirements.txt

Упражнение 18.1

Создайте изолированное окружение для проекта:

  1. Создайте venv и активируйте его
  2. Установите 3 полезные библиотеки для работы с данными
  3. Создайте requirements.txt
  4. Инициализируйте проект с помощью Poetry
  5. Добавьте зависимости через Poetry

Глава 19: Работа с данными (Pandas)

Pandas - мощная библиотека для анализа и обработки данных.

19.1 Основы Pandas

import pandas as pd

# Создание DataFrame
data = {
    "Имя": ["Анна", "Борис", "Виктор"],
    "Возраст": [25, 30, 35],
    "Город": ["Москва", "СПб", "Казань"]
}
df = pd.DataFrame(data)
print(df)

# Основные операции
print(df.head(2)) # Первые 2 строки
print(df.describe()) # Статистика
print(df["Возраст"].mean()) # Средний возраст
print(df[df["Возраст"] > 30]) # Фильтрация

19.2 Чтение и анализ данных

# Чтение CSV
df = pd.read_csv("data.csv", encoding='utf-8')

# Очистка данных
df = df.dropna() # Удаление пропусков
df["Дата"] = pd.to_datetime(df["Дата"]) # Конвертация дат

# Группировка и агрегация
grouped = df.groupby("Город")["Продажи"].sum()
print(grouped)

# Визуализация
df.plot(kind='bar', x='Город', y='Продажи')
plt.title('Продажи по городам')
plt.show()

Упражнение 19.1

Проанализируйте набор данных:

  1. Загрузите CSV с данными о продажах
  2. Очистите данные (пропуски, некорректные значения)
  3. Рассчитайте суммарные продажи по месяцам
  4. Найдите топ-3 товара по продажам
  5. Постройте график динамики продаж

Глава 20: Веб-разработка (FastAPI)

FastAPI - современный фреймворк для создания API.

20.1 Создание API

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float
    is_offer: bool = None

@app.get("/")
async def read_root():
    return {"message": "Hello World"}

@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "q": q}

@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    return {"item_name": item.name, "item_id": item_id}

20.2 Документация и аутентификация

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

def fake_decode_token(token):
    return {"username": token + "user"}

async def get_current_user(token: str = Depends(oauth2_scheme)):
    user = fake_decode_token(token)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid authentication credentials"
        )
    return user

@app.get("/users/me")
async def read_users_me(current_user: dict = Depends(get_current_user)):
    return current_user
Автоматическая документация: После запуска приложения документация будет доступна по адресам:
  • /docs - интерактивная документация (Swagger UI)
  • /redoc - альтернативная документация

Упражнение 20.1

Создайте простое API для блога:

  1. Реализуйте CRUD операции для статей
  2. Добавьте аутентификацию для защищенных endpoints
  3. Добавьте поиск по статьям
  4. Реализуйте пагинацию для списка статей