Урок 4: Взаимодействие с внешним миром и продвинутые концепции

Привет! Надеюсь, ты уже немного попрактиковался с ООП и создал пару-тройку классов. Сегодня мы выйдем за пределы твоего компьютера и научимся общаться с внешним миром: интернетом, базами данных и другими программами.


Часть 1: «Позвони мне» — Работа с HTTP-запросами (библиотека requests)

Часто твоей программе нужно получать данные из интернета: погоду, курсы валют, посты из соцсетей. Для этого используются HTTP-запросы. В Python есть прекрасная библиотека requests, которая делает это очень просто.

Установка:

pip install requests

Простейший GET-запрос (получить данные):

import requests

# Получаем случайный факт о котах
response = requests.get('https://catfact.ninja/fact')

# Проверяем, что запрос успешен (статус 200)
if response.status_code == 200:
    data = response.json()  # Преобразуем JSON-ответ в словарь Python
    print("Случайный факт о котах:", data['fact'])
else:
    print("Ошибка при запросе:", response.status_code)

Более сложный пример — получение погоды:

import requests

def get_weather(city):
    # Используем бесплатное API OpenWeatherMap (нужно зарегистрироваться для получения ключа)
    api_key = "твой_ключ_здесь"  # Получи на openweathermap.org
    url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric&lang=ru"
    
    try:
        response = requests.get(url)
        if response.status_code == 200:
            data = response.json()
            city_name = data['name']
            temp = data['main']['temp']
            description = data['weather'][0]['description']
            print(f"Погода в {city_name}: {temp}°C, {description}")
        else:
            print(f"Город '{city}' не найден")
    except requests.exceptions.ConnectionError:
        print("Ошибка соединения с интернетом")

# Использование
get_weather("Moscow")
get_weather("London")

Часть 2: «Помни всё надолго» — Работа с базами данных (SQLite)

Файлы — это хорошо, но для структурированных данных лучше подходят базы данных. SQLite — это легкая база данных, которая хранится в одном файле и не требует установки сервера. Идеально для обучения и небольших проектов!

Создаем базу данных и таблицу:

import sqlite3

# Подключаемся к базе (файл создастся автоматически)
conn = sqlite3.connect('my_database.db')
cursor = conn.cursor()

# Создаем таблицу пользователей
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL,
    age INTEGER
)
''')

# Сохраняем изменения и закрываем соединение
conn.commit()
conn.close()
print("База данных создана!")

CRUD-операции (Create, Read, Update, Delete):

# Добавление данных (CREATE)
def add_user(name, email, age):
    conn = sqlite3.connect('my_database.db')
    cursor = conn.cursor()
    
    try:
        cursor.execute('INSERT INTO users (name, email, age) VALUES (?, ?, ?)', 
                      (name, email, age))
        conn.commit()
        print(f"Пользователь {name} добавлен!")
    except sqlite3.IntegrityError:
        print("Пользователь с таким email уже существует")
    finally:
        conn.close()

# Чтение данных (READ)
def get_all_users():
    conn = sqlite3.connect('my_database.db')
    cursor = conn.cursor()
    
    cursor.execute('SELECT * FROM users')
    users = cursor.fetchall()  # Получаем все записи
    
    conn.close()
    return users

# Использование
add_user("Иван Иванов", "ivan@mail.ru", 25)
add_user("Петр Петров", "petr@mail.ru", 30)

users = get_all_users()
print("Все пользователи:")
for user in users:
    print(f"ID: {user[0]}, Имя: {user[1]}, Email: {user[2]}, Возраст: {user[3]}")

Часть 3: «Делай это красиво» — Декораторы

Декораторы — одна из самых элегантных возможностей Python. Это функции, которые «оборачивают» другие функции, добавляя им новое поведение, не меняя их код.

Простейший декоратор:

def my_decorator(func):
    def wrapper():
        print("Что-то происходит перед вызовом функции")
        func()  # Вызываем оригинальную функцию
        print("Что-то происходит после вызова функции")
    return wrapper

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

say_hello()
# Выведет:
# Что-то происходит перед вызовом функции
# Привет!
# Что-то происходит после вызовом функции

Практический пример — декоратор для замера времени:

import time

def timer(func):
    def wrapper(*args, **kwargs):  # *args и **kwargs позволяют принимать любые аргументы
        start_time = time.time()
        result = func(*args, **kwargs)  # Вызываем оригинальную функцию
        end_time = time.time()
        print(f"Функция {func.__name__} выполнялась {end_time - start_time:.4f} секунд")
        return result
    return wrapper

@timer
def slow_function():
    # Имитируем долгую операцию
    time.sleep(2)
    print("Функция завершена")

@timer
def fast_function():
    print("Быстрая функция завершена")

slow_function()
fast_function()

Часть 4: Практика — создаем мини-приложение

Давай создадим простое консольное приложение для учета задач с использованием БД и HTTP-запросов (для разнообразия).

import sqlite3
import requests
from datetime import datetime

class TaskManager:
    def __init__(self, db_name='tasks.db'):
        self.db_name = db_name
        self._create_table()
    
    def _create_table(self):
        conn = sqlite3.connect(self.db_name)
        cursor = conn.cursor()
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS tasks (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                title TEXT NOT NULL,
                description TEXT,
                created_at TEXT,
                completed BOOLEAN DEFAULT FALSE
            )
        ''')
        conn.commit()
        conn.close()
    
    def add_task(self, title, description=""):
        conn = sqlite3.connect(self.db_name)
        cursor = conn.cursor()
        
        created_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        cursor.execute('''
            INSERT INTO tasks (title, description, created_at) 
            VALUES (?, ?, ?)
        ''', (title, description, created_at))
        
        conn.commit()
        conn.close()
        print(f"Задача '{title}' добавлена!")
    
    def show_tasks(self):
        conn = sqlite3.connect(self.db_name)
        cursor = conn.cursor()
        
        cursor.execute('SELECT * FROM tasks WHERE completed = FALSE')
        tasks = cursor.fetchall()
        
        conn.close()
        
        if not tasks:
            print("Нет активных задач!")
            return
        
        print("\n--- Активные задачи ---")
        for task in tasks:
            status = "✓" if task[4] else "☐"
            print(f"{task[0]}. [{status}] {task[1]} - {task[3]}")
    
    def complete_task(self, task_id):
        conn = sqlite3.connect(self.db_name)
        cursor = conn.cursor()
        
        cursor.execute('UPDATE tasks SET completed = TRUE WHERE id = ?', (task_id,))
        conn.commit()
        conn.close()
        print(f"Задача {task_id} выполнена!")
    
    def get_inspirational_quote(self):
        """Получаем случайную мотивирующую цитату"""
        try:
            response = requests.get('https://api.quotable.io/random')
            if response.status_code == 200:
                data = response.json()
                return f"🎯 {data['content']} — {data['author']}"
        except:
            return "🚀 Ты можешь всё! Продолжай в том же духе!"

# Главная программа
def main():
    manager = TaskManager()
    
    while True:
        print("\n=== МЕНЕДЖЕР ЗАДАЧ ===")
        print("1. Добавить задачу")
        print("2. Показать задачи")
        print("3. Завершить задачу")
        print("4. Мотивация")
        print("5. Выход")
        
        choice = input("Выберите действие: ")
        
        if choice == '1':
            title = input("Введите название задачи: ")
            description = input("Введите описание (необязательно): ")
            manager.add_task(title, description)
        
        elif choice == '2':
            manager.show_tasks()
        
        elif choice == '3':
            task_id = input("Введите ID задачи для завершения: ")
            manager.complete_task(task_id)
        
        elif choice == '4':
            print(manager.get_inspirational_quote())
        
        elif choice == '5':
            print("До свидания!")
            break
        
        else:
            print("Неверный выбор!")

if __name__ == "__main__":
    main()

Что можно улучшить (задания для тебя): 1. Добавь возможность редактирования задач 2. Сделай категории для задач 3. Добавь напоминания о просроченных задачах 4. Реализуй экспорт задач в файл


Что дальше?

Ты теперь умеешь очень многое! Следующие возможные темы: – Веб-фреймворки (Django/Flask) — для создания веб-приложений – Асинхронное программирование (async/await) — для высокопроизводительных приложений – Data Science (pandas, numpy) — для анализа данных – GUI (Tkinter, PyQt) — для создания оконных приложений – Тестирование (pytest) — для написания надежного кода

Совет: Выбери то, что тебе интереснее всего, и углубляйся в эту тему. Не пытайся выучить всё сразу!

Ты прошел огромный путь от простых переменных до создания полноценных приложений. Гордись собой! Помни: лучший способ учиться — создавать проекты, которые тебе действительно интересны.

Удачи в твоем путешествии в мир Python! 🐍✨