es
Feedback
Python для начинающих

Python для начинающих

Ir al canal en Telegram

Python для начинающих

Mostrar más
1 240
Suscriptores
+124 horas
+37 días
+230 días
Archivo de publicaciones
Привет! С вами Иван, и сегодня мы разберём одну из самых неоднозначных истин программиста: унаследованный код и сторонние библиотеки — это не враги, а будущие союзники! Когда впервые сталкиваешься с чужими проектами или старыми библиотеками, кажется, будто попал в таинственный квест без карты. Однако Python предоставляет инструменты, чтобы не только "выжить" среди многолетних конструкций, но и укротить их под свои нужды. ### Исследуем незнакомый код Для начала важно быстро понять структуру чужой библиотеки. Поможет модуль inspect:
import inspect
import math

print(inspect.getmembers(math, inspect.isfunction))
Этот фрагмент выведет все функции модуля math. Так вы сразу увидите, чем можно воспользоваться, не лезя в исходники. ### Переосмысливаем поведение Допустим, сторонняя функция работает не совсем так, как хочется. На помощь приходит паттерн "обертки":
from some_old_library import too_simple_func

def my_func(*args, **kwargs):
    result = too_simple_func(*args, **kwargs)
    if result is None:
        raise ValueError("Это слишком просто!")
    return result
Такой подход добавляет нужную проверку, не трогая оригинал. ### Замена или расширение классов Наследуемый класс хранит логику, которую вы бы немного изменили? Подклассируете!
from legacy_package import OldClass

class NewClass(OldClass):
    def calculate(self, x):
        result = super().calculate(x)
        return result * 2
Теперь старый функционал расширен без потери совместимости. ### Отладка без стресса Модуль logging помогает понять, что происходит внутри:
import logging

logging.basicConfig(level=logging.DEBUG)

def wrapped_func(*args):
    logging.debug("Arguments: %s", args)
    return too_simple_func(*args)
Логи позволяют действовать осознанно, даже если документация минимальна. ### Важный совет от Ивана Не бойтесь экспериментировать с чужим кодом (только не в продакшене!). Модули inspect, unittest.mock, обертки и наследование — ваши друзья. С их помощью даже ветхое наследие превратится в прочную базу для новых идей. До встречи в следующих коротких, но ёмких разборках!

Как работать с унаследованными кодами и библиотеками в Python
Как работать с унаследованными кодами и библиотеками в Python

Привет! С вами Иван, и сегодня мы разберёмся с созданием собственных Python-пакетов для повторного использования кода c помощью setuptools. Терпеть не могу копировать функции из одного проекта в другой! К счастью, Python позволяет упаковать полезные модули, чтобы потом легко их устанавливать через pip. ## Почему это важно? Рано или поздно каждый сталкивается с ситуацией: вот отличная функция для обработки даты, и вот она снова нужна — в новом проекте. Перетаскивать файлы вручную – прошлый век! Пакеты решают эту проблему. Помимо удобства, это ещё и первый шаг к публикации в PyPI. ## Минимальный пакет: поехали! Для примера создадим папку awesome_math, а внутри — файл operations.py:
# operations.py
def add(a, b):
    return a + b

def multiply(a, b):
    return a * b
Теперь создадим файл __init__.py (даже если он пустой):
# __init__.py
from .operations import add, multiply
Скелет готов! ## Настраиваем setup.py Теперь самая магия — setup.py:
from setuptools import setup, find_packages

setup(
    name="awesome_math",
    version="0.1",
    packages=find_packages(),
    author="Ivan",
    description="Sample package for math operations",
    python_requires=">=3.6",
)
## Установка пакета Перейдите в папку выше и установите пакет локально:
pip install -e ./awesome_math
Флаг -e (“editable”) позволяет менять код пакета на лету — удобно для отладки. ## Используем в реальном коде Готово! Теперь можно импортировать функции из любого места:
from awesome_math import add, multiply

print(add(2, 3))        # 5
print(multiply(4, 5))   # 20
## Итоги Создавать свои пакеты с помощью setuptools — просто и удобно. Такой подход организует код, ускоряет разработку и позволяет делиться своими наработками с коллегами (или со всем миром!). Я всегда советую автоматизировать повторяющиеся задачи, а свой пакет — лучший способ избавиться от рутины.

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

Привет! С вами Иван, и сегодня я расскажу о таинственном царстве двоичных (binary) файлов в Python. Мы так привыкли работать с текстом, что забываем: музыка, картинки, да что уж там — даже документ Word — внутри состоят из байтов, а не буковок. ## Чем отличаются двоичные файлы? Когда мы читаем или пишем файл в текстовом режиме, Python заботится о кодировке: превращает байты в строки и обратно. Но с бинарными данными так не получится — они воспринимаются как сырые байты (bytes). Это важно, если вы, например, работаете с изображениями или сериализуете объекты. ## Как открыть двоичный файл? Легко! Достаточно добавить к режиму 'r', 'w' или 'a' букву 'b':
with open('example.bin', 'wb') as bin_file:
    bin_file.write(b'Hello, world!')
Здесь 'wb' означает write binary — никаких странных символов перевода строки и прочих неожиданностей. ## Чтение двоичных файлов Открываем файл в режиме 'rb'— читаем байты:
with open('example.bin', 'rb') as bin_file:
    data = bin_file.read()
    print(data)  # Выведет: b'Hello, world!'
Получили на выходе тип bytes. Каждый элемент такого объекта — число от 0 до 255. ## Запись последовательности байтов Все просто: передаем в write объект bytes или bytearray. Например, сохраним несколько чисел в файл:
numbers = [27, 255, 128, 42]
byte_data = bytes(numbers)
with open('numbers.bin', 'wb') as bin_file:
    bin_file.write(byte_data)
## Немного магии с модулем struct Если нужно упаковать не просто числа, а, например, float или значения разных типов, поможет модуль struct — он превращает числа и структуры в байты и обратно:
import struct

packed = struct.pack('if', 7, 3.14)  # 'i' — целое, 'f' — float
with open('struct.bin', 'wb') as bin_file:
    bin_file.write(packed)
А вот как распаковать обратно:
with open('struct.bin', 'rb') as bin_file:
    data = bin_file.read()
    number, value = struct.unpack('if', data)
    print(number, value)  # 7 3.14
## Итоги Двоичные файлы — не страшное чудовище, а удобный способ для работы с «сырыми» данными любого типа. Их невозможно случайно «испортить» сменой кодировки, зато можно ловко управлять байтами и экономить место.

Работа с двоичными файлами: чтение и запись с помощью байтов
Работа с двоичными файлами: чтение и запись с помощью байтов

Привет, меня зовут Иван, и сегодня я расскажу тебе, как устроить себе настоящий мини-сервер ― буквально в пару строк! Если ты только начинаешь своё путешествие в мир Python и веба, модуль wsgiref — это твой пропуск на этот интересный уровень. ### Что такое WSGI и зачем он нужен? WSGI (Web Server Gateway Interface) — это стандарт, который помогает Python-программам общаться с веб-серверами. Встроенный модуль Python wsgiref — это как виртуальный щит, который превращает твой код в простой веб-сервер. Он отлично подходит для тестов и экспериментов — идеально для начинающих! ### Первый пример: “Hello, world!” Создадим файл server.py:
from wsgiref.simple_server import make_server

def simple_app(environ, start_response):
    status = '200 OK'
    headers = [('Content-type', 'text/plain; charset=utf-8')]
    start_response(status, headers)
    return [b"Hello, world!"]

if __name__ == '__main__':
    server = make_server('localhost', 8080, simple_app)
    print("Serving on http://localhost:8080/ ...")
    server.serve_forever()
Запускай скрипт, переходи в браузере на http://localhost:8080 — и ты увидишь волшебное “Hello, world!”. Именно так начинается путь любого веб-разработчика. ### Как это работает? - make_server создает сервер и принимает три параметра: адрес, порт и функцию-приложение. - simple_app — “основное блюдо”. Она получает две переменные: данные о запросе (environ) и функцию для передачи статуса с заголовками (start_response). - Возвращаемый список содержит байты, которые отдаются в ответ пользователю. ### А если хочется HTML? Легко! Вот пример функции, отдающей HTML:
def html_app(environ, start_response):
    status = '200 OK'
    headers = [('Content-type', 'text/html; charset=utf-8')]
    start_response(status, headers)
    html = """
    <html>
        <head><title>WSGI Test</title></head>
        <body><h1>Привет из wsgiref!</h1></body>
    </html>
    """
    return [html.encode('utf-8')]
### Поддержка разных путей Хочешь разные ответы по разным URL? Используй environ['PATH_INFO']:
def path_app(environ, start_response):
    path = environ.get('PATH_INFO', '/')
    if path == '/about':
        body = "This is the About page."
    else:
        body = "Home page."
    status = '200 OK'
    headers = [('Content-type', 'text/plain; charset=utf-8')]
    start_response(status, headers)
    return [body.encode('utf-8')]
Добавь эту функцию в make_server — и твой сервер стал умнее! --- Вот так легко можно войти в веб-мир Python, используя стандартные инструменты. Не нужен ни Flask, ни Django, ни танцы с бубном — только чистый Python и твоя фантазия!

Как настроить локальный сервер с использованием модуля wsgiref
Как настроить локальный сервер с использованием модуля wsgiref

Как настроить локальный сервер с использованием модуля wsgiref
Как настроить локальный сервер с использованием модуля wsgiref

## Schedule — твой персональный дирижёр в мире повторяющихся задач Всем привет! С вами Иван, и сегодня мы поговорим о настоящей находке для каждого, кто устал вручную запускать одни и те же функции в Python. Представляю вам модуль schedule — отличный инструмент для простого управления повторяющимися задачами. ### Что это такое? Модуль schedule позволяет легко и понятно запускать ваши Python-функции по расписанию: каждый день, каждый час, по выходным или хоть каждую пятую минуту. На вид — как мини-крон прямо внутри кода, только гораздо дружелюбнее. ### Установка Перед стартом — минутка магии в консоли:
pip install schedule
### Примеры использования Разберём на пальцах. Допустим, вы хотите, чтобы скрипт отправлял напоминание выпить воды каждый час. Вот как это делается:
import schedule
import time

def remind_water():
    print("Time to drink some water!")

schedule.every(1).hour.do(remind_water)

while True:
    schedule.run_pending()
    time.sleep(1)
Теперь функция remind_water будет срабатывать раз в час, пока скрипт работает. А если нужно выполнять задачу только по рабочим дням — не проблема!
def check_email():
    print("Don't forget to check your email!")

schedule.every().monday.do(check_email)
schedule.every().tuesday.do(check_email)
schedule.every().wednesday.do(check_email)
schedule.every().thursday.do(check_email)
schedule.every().friday.do(check_email)
Можно и покреативить: запускать задачу каждые 10 минут или, скажем, в определённое время суток:
def backup_files():
    print("Backup started!")

schedule.every(10).minutes.do(backup_files)
schedule.every().day.at("23:00").do(backup_files)
### Фишки модуля - schedule.run_pending() проверяет — не пора ли что запустить, и делает это. - Время можно указывать сразу для нескольких задач с разной периодичностью. - Работает просто: без лишних настроек, конфигов и заморочек. ### Минусы и ограничения Модуль не умеет работать в фоне — если закроете скрипт, задачи выполняться не будут. Для продвинутых сценариев (например, для серверов) нужны другие решения, но для учебных и простых домашних проектов schedule — настоящее спасение. Практикуйте и экспериментируйте, ведь расписание — ключ к продуктивности даже в программировании!

Использование модели повторяющихся задач с schedule
Использование модели повторяющихся задач с schedule

Привет, друзья! С вами Иван, и сегодня мы погрузимся в захватывающий мир многопоточности на Python с помощью модуля threading. Даже если вы пока не запускали код "параллельно", этот пост для вас! ### Что такое потоки и зачем они нужны? Обычно Python выполняет код последовательно. Но что если вам нужно скачивать картинки, опрашивать API и тут же обновлять интерфейс? Здесь на сцену выходит threading — стандартный модуль для работы с потоками. Потоки (threads) позволяют запускать функции параллельно, не ожидая завершения одной, чтобы стартовать другую. ### Простой пример: запуск двух задач одновременно Посмотрим, как это выглядит на практике:
import threading
import time

def print_numbers():
    for i in range(5):
        print(f"Number: {i}")
        time.sleep(1)

def print_letters():
    for letter in 'abcde':
        print(f"Letter: {letter}")
        time.sleep(1)

t1 = threading.Thread(target=print_numbers)
t2 = threading.Thread(target=print_letters)

t1.start()
t2.start()

t1.join()
t2.join()
print("Done!")
Две функции работают параллельно: одна выводит числа, другая — буквы. ### Как управлять потоками? - Создание: каждый поток — это экземпляр threading.Thread, который принимает функцию через параметр target, и ее аргументы через args. - Запуск: .start() начинает выполнение в новом потоке. - Ожидание завершения: .join() блокирует основной поток, пока дочерний не закончится. ### А если нужно знать, работает ли поток?
worker = threading.Thread(target=time.sleep, args=(3,))
worker.start()
print(worker.is_alive())  # True
worker.join()
print(worker.is_alive())  # False
Метод is_alive() вернет True, пока поток еще трудится. ### Безопасность данных — используем Lock Потоки могут обращаться к одним и тем же данным, поэтому важно использовать блокировки (Lock):
counter = 0
lock = threading.Lock()

def increment():
    global counter
    for _ in range(1000):
        with lock:
            counter += 1

threads = [threading.Thread(target=increment) for _ in range(10)]
for t in threads: t.start()
for t in threads: t.join()
print(counter)  # Всегда 10000!
Lock гарантирует, что только один поток изменяет переменную в конкретный момент. --- threading открывает путь к одновременному исполнению кода и ускоряет задачи ввода-вывода. Главное — не забывайте про безопасный доступ к общим данным, и тогда ваши приложения станут гораздо мощнее!

Создание и управление потоками с использованием threading
Создание и управление потоками с использованием threading

Привет, друзья! На связи Иван, и сегодня мы окунемся в мир Python-модуля, который любит любой ценитель изящного кода — речь о itertools. Этот модуль открыт как сундук с сокровищами для разных комбинаторных задач: от банального перебора вариантов до создания хитроумных перестановок. ## Зачем вообще нужен itertools? Когда возникает задача "перебрать все комбинации", "замиксовать значения" или "иcкать все варианты", большинство новичков берёт в руки вложенные циклы и — устаёт. Но если вы знаете про itertools, эти задачи превращаются в пару строк элегантного кода. Давайте разбираться с основами! ### 1. Комбинации Выберите любые 2 книги из 4-х? За нас всё сделает itertools.combinations:
from itertools import combinations

books = ['The Hobbit', 'Python 101', 'Moby Dick', 'War and Peace']
for combo in combinations(books, 2):
    print(combo)
Этот код выведет все возможные пары книг — и ни одна не повторится. ### 2. Перестановки Все возможные варианты порядка трёх футболистов на пьедестале? Простая задача для permutations:
from itertools import permutations

players = ['Alice', 'Bob', 'Charlie']
for p in permutations(players):
    print(p)
Здесь будет 6 вариантов (3!) — идеально для задач, где важен порядок. ### 3. Произведения (Декартово произведение) Когда нужно смиксовать элементы из разных коллекций, используем product:
from itertools import product

colors = ['red', 'green']
sizes = ['S', 'M']
for item in product(colors, sizes):
    print(item)
Ты быстро получаешь комбинации вида: ('red', 'S'), ('red', 'M'), … ### 4. Комбинации с повторениями Допустим, нужно узнать, какие мороженое можно собрать из 3-х шариков, если вкусы могут повторяться:
from itertools import combinations_with_replacement

flavors = ['chocolate', 'vanilla', 'strawberry']
for combo in combinations_with_replacement(flavors, 3):
    print(combo)
Получаем все возможные варианты с повторениями, без головной боли! --- itertools — это как швейцарский нож для работы с итерациями. Освоив всего несколько функций, ты вытесняешь громоздкие циклы лаконичными генераторами. Заходи в документацию и пробуй новые инструменты — и Python станет для тебя ещё более мощным и гибким!

Как работает itertools: от простых комбинаций до сложных перестановок
Как работает itertools: от простых комбинаций до сложных перестановок

Привет! С вами Иван, сегодня копнем чуточку глубже — поговорим о метаклассах в Python. Многие слышали про метаклассы как о чем-то мистическом, но на деле — это просто классы, которые создают другие классы. Да-да, в Python даже классы — это объекты, и за тем, как они создаются, следит метакласс. В обычной жизни мы редко сталкиваемся с ними, но если нужно гибко и аккуратно управлять поведением всех классов в проекте — метаклассы становятся отличным инструментом. ## Для чего нужны метаклассы? С их помощью можно: - Автоматически модифицировать классы при создании (например, добавлять методы или атрибуты); - Навязывать единый стиль (например, проверять именование или структуру классов); - Реализовывать паттерны, вроде Singleton, прямо “на уровне класса”. ## Базовый пример Создадим метакласс, который автоматически добавляет атрибут category = 'custom_class' во все классы:
class BaseMeta(type):
    def __new__(mcs, name, bases, attrs):
        attrs['category'] = 'custom_class'
        return super().__new__(mcs, name, bases, attrs)

class ExampleClass(metaclass=BaseMeta):
    pass

print(ExampleClass.category)  # custom_class
## Валидация структуры класса Иногда хочется убедиться, что каждый класс имеет нужные методы:
class MethodCheckerMeta(type):
    def __new__(mcs, name, bases, attrs):
        if 'process' not in attrs:
            raise TypeError('Class must define "process" method')
        return super().__new__(mcs, name, bases, attrs)

class DataWorker(metaclass=MethodCheckerMeta):
    def process(self):
        print("Processing...")

# class BadWorker(metaclass=MethodCheckerMeta):
#     pass  # Ошибка при определении класса!
## Подмена методов на лету Допустим, хотим, чтобы все методы начинали логировать своё вызовы:
def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f'Call {func.__name__}')
        return func(*args, **kwargs)
    return wrapper

class LoggerMeta(type):
    def __new__(mcs, name, bases, attrs):
        for key, val in attrs.items():
            if callable(val):
                attrs[key] = log_decorator(val)
        return super().__new__(mcs, name, bases, attrs)

class UserAction(metaclass=LoggerMeta):
    def update_profile(self):
        print("Profile updated")

u = UserAction()
u.update_profile()
Как видите, метаклассы — секретная дверца Python к по-настоящему мощным и гибким фичам. Пользуются ими редко, но знать о них точно стоит!

Работа с метаклассами: расширенное использование классов
Работа с метаклассами: расширенное использование классов

Привет! На связи Иван, и сегодня в нашем блоге разберём магию перенаправления потоков ввода и вывода в Python. Зачем это нужно? Например, если вы хотите записывать вывод вашей программы не только на экран, но и в файл, или "обмануть" функцию, которая традиционно ждёт пользовательский ввод, подсовывая ей данные автоматически. Готовы? Погнали! ## Перенаправляем stdout: вывод в файл и обратно Для работы с потоками в Python служит модуль sys. Самый популярный поток — это sys.stdout, который по умолчанию пишет в консоль. Давайте заставим его писать в файл:
import sys

with open('output.txt', 'w') as file:
    original_stdout = sys.stdout  # сохраняем ссылку на стандартный поток
    sys.stdout = file             # перенаправляем stdout в файл
    print("Hello, file!")
    sys.stdout = original_stdout  # возвращаем stdout обратно

print("Hello, console!")
Теперь строка "Hello, file!" попадёт в файл, а "Hello, console!" — как обычно, в терминал. ## Подменяем stdin: автоматизируем ввод Точно так же можно подменить поток ввода. Это удобно, когда нужно тестировать функции, требующие input от пользователя.
import sys
from io import StringIO

test_input = StringIO('42\n')
original_stdin = sys.stdin
sys.stdin = test_input

number = int(input("Enter a number: "))
print("Number x2:", number * 2)

sys.stdin = original_stdin
В этом примере input не ждёт ввода, а сразу получает '42'. Удобно для юнит-тестов! ## А если хочется перехватить вывод программы? Трюк с подменой stdout особенно крут, когда хочется легко перехватывать и анализировать результат работы каких-то функций. Например, сделаем функцию, возвращающую всё, что она напечатала:
def capture_output(func):
    import sys
    from io import StringIO

    output = StringIO()
    original_stdout = sys.stdout
    sys.stdout = output
    try:
        func()
    finally:
        sys.stdout = original_stdout
    return output.getvalue()

def hello():
    print("Hello from function!")

text = capture_output(hello)
print("Captured:", text)
Теперь мы можем обработать результат как строку — не круто ли? На этом всё! Не стесняйтесь экспериментировать с потоками: это ключ к автоматизации, тестированию и оптимизации ваших программ. Желаю отличной практики и новых открытий с Python! Иван.

Как переназначить поток вывода и ввода в Python
Как переназначить поток вывода и ввода в Python

Привет! С вами Иван. Сегодня разберём одну из самых закулисных и магических тем Python — управление памятью: подсчёт ссылок и сборку мусора. Если вы когда-нибудь задумывались, почему Python не просит у вас явно освобождать память, то этот пост для вас! ## Подсчёт ссылок: сколько “рук” держат объект? Python использует reference counting — счётчик ссылок на каждый объект. Когда переменная указывает на объект, счётчик увеличивается. Как только ни одна переменная на него больше не ссылается, объект считается “ненужным” и подлежит удалению. Пример:
import sys

a = []
print(sys.getrefcount(a))  # Обычно вернёт 2 (a и аргумент функции)
b = a
print(sys.getrefcount(a))  # Уже 3 ссылки (a, b, и аргумент)
del b
print(sys.getrefcount(a))  # Снова 2
Магия проста: пока есть хотя бы одна “рука”, держащая объект, он живёт. Как только все переменные и ссылки исчезают — память освобождается. ## Сборка мусора: борьба с “каруселями” Но что, если объекты ссылаются друг на друга? Простое удаление переменных не сработает — каждый будет держать “за руку” другого, и счётчики не опустятся до нуля! Тут появляется garbage collector. В Python модуль gc следит за такими “каруселями”:
import gc

class Node:
    def __init__(self):
        self.ref = None

x = Node()
y = Node()
x.ref = y
y.ref = x

del x, y  # Ссылок на объекты нет, но карусель всё ещё существует
gc.collect()  # Явно собираем мусор, объекты будут удалены
Garbage collector периодически сканирует объекты, чтобы найти непростые циклы, и удаляет их, когда доступ к ним невозможен. ## Практические советы - Не бойтесь “загрязнить” память — Python делает всё сам. - Если работаете с большим количеством данных и видите рост памяти — попробуйте вызвать gc.collect(). - Используйте weakref, если нужен временный “тонкий” доступ без увеличения счётчика ссылок. Пусть ваша память всегда будет свободна для новых идей!