🐍 Python Deque: Когда обычного списка недостаточно
Многие используют стандартный
Здесь на сцену выходит
🚀 Почему Deque круче списка в определенных задачах?
Главная проблема
🔹
🔹Возможность создания кольцевых буферов (ограниченных очередей).
🔹Потокобезопасность для атомарных операций добавления/удаления.
🛠 Примеры использования
💡 Когда стоит использовать
🔹Реализация очередей (FIFO) и стеков (LIFO).
🔹Алгоритмы обхода графов (BFS - поиск в ширину).
🔹Хранение последних логов или сообщений.
📖 Подробнее в статье: https://realpython.com/python-deque/
#python #tips #collections #backend
👉 @python_real
Многие используют стандартный
list для любых задач, связанных с хранением последовательностей. Но что, если вам нужно эффективно добавлять или удалять элементы с обоих концов структуры?Здесь на сцену выходит
collections.deque (double-ended queue).🚀 Почему Deque круче списка в определенных задачах?
Главная проблема
list в том, что он оптимизирован для операций с правой стороны. Удаление или вставка в начало списка (list.insert(0, v) или list.pop(0)) заставляет Python сдвигать все остальные элементы, что дает сложность .deque обеспечивает:🔹
O(1) для операций добавления/удаления как слева, так и справа.🔹Возможность создания кольцевых буферов (ограниченных очередей).
🔹Потокобезопасность для атомарных операций добавления/удаления.
🛠 Примеры использования
from collections import deque
# 1. Создаем дек
d = deque(['middle'])
# 2. Добавляем элементы с двух сторон
d.append('right') # в конец
d.appendleft('left') # в начало
print(d) # deque(['left', 'middle', 'right'])
# 3. Удаляем элементы
d.pop()
d.popleft()
# 4. Ограниченная очередь (самое полезное!)
# Хранит только последние 3 элемента. Идеально для логов или истории.
history = deque(maxlen=3)
for i in range(5):
history.append(f"Action {i}")
print(history)
# Результат: всегда только последние 3 действия
💡 Когда стоит использовать
deque?🔹Реализация очередей (FIFO) и стеков (LIFO).
🔹Алгоритмы обхода графов (BFS - поиск в ширину).
🔹Хранение последних логов или сообщений.
Важный нюанс: Доступ к элементам по индексу в середине дека (d[n]) работает медленнее(O(n)), чем в списке(O(1)). Если вам нужен частый произвольный доступ - оставайтесь наlist.
📖 Подробнее в статье: https://realpython.com/python-deque/
#python #tips #collections #backend
👉 @python_real
👍5
🐍 Создаем классическую «Змейку» на Python за 15 минут!
Помните те времена, когда мы часами залипали в «Змейку» на старых Nokia? Самое крутое, что механику этой легендарной игры можно воссоздать на Python, используя библиотеку
Это отличный проект для тех, кто хочет подтянуть навыки работы с игровыми циклами, обработкой событий и координатной сеткой.
🛠 Что внутри проекта?
1. Игровое поле: Создаем окно и задаем цвета.
2. Змейка: Представляем её как список координат блоков.
3. Логика движения: Обрабатываем нажатия клавиш (вверх, вниз, влево, вправо).
4. Еда и рост: Генерируем «яблоки» в случайных местах и увеличиваем длину змейки при поедании.
5. Game Over: Условия столкновения со стенами или собственным хвостом.
💻 Кусочек кода для старта:
В статье подробно разобрано, как собрать всё воедино, настроить экран проигрыша и добавить счетчик очков.
📖 Подробнее: https://towardsdatascience.com/implementing-the-snake-game-in-python/
#python #pygame #coding #gameloop #tutorial
👉 @python_real
Помните те времена, когда мы часами залипали в «Змейку» на старых Nokia? Самое крутое, что механику этой легендарной игры можно воссоздать на Python, используя библиотеку
pygame.Это отличный проект для тех, кто хочет подтянуть навыки работы с игровыми циклами, обработкой событий и координатной сеткой.
🛠 Что внутри проекта?
1. Игровое поле: Создаем окно и задаем цвета.
2. Змейка: Представляем её как список координат блоков.
3. Логика движения: Обрабатываем нажатия клавиш (вверх, вниз, влево, вправо).
4. Еда и рост: Генерируем «яблоки» в случайных местах и увеличиваем длину змейки при поедании.
5. Game Over: Условия столкновения со стенами или собственным хвостом.
💻 Кусочек кода для старта:
import pygame
import time
# Инициализация
pygame.init()
white = (255, 255, 255)
snake_speed = 15
# Основной цикл игры
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
# Тут происходит вся магия движения...
В статье подробно разобрано, как собрать всё воедино, настроить экран проигрыша и добавить счетчик очков.
📖 Подробнее: https://towardsdatascience.com/implementing-the-snake-game-in-python/
#python #pygame #coding #gameloop #tutorial
👉 @python_real
👍2🍾2
🚀 Pydantic AI: Создаем типобезопасных LLM-агентов на Python
Если вы устали писать костыли для парсинга сырого текста от LLM, этот инструмент решает проблему изящно: вы задаете схемы через
Что разбирается в статье:
• Структурированный вывод: Как заставить агента возвращать строго типизированные объекты вместо "простыни" текста.
• Использование инструментов (Tool Calling): Как с помощью простого декоратора
• Dependency Injection: Безопасный проброс контекста (сессий БД, настроек) в агенты и инструменты с проверкой типов через
• Подводные камни: Честный разбор ограничений - как ретраи влияют на расход токенов, стоимость API и почему для масштабных проектов с кучей готовых интеграций всё еще может понадобиться LangChain или LlamaIndex.
Кому будет полезно?
Всем, кто хочет быстро прототипировать ИИ-фичи с минимальным количеством бойлерплейта и максимальным контролем над типами данных.
🔗 Читать туториал полностью: https://realpython.com/pydantic-ai/
#python #pydantic #llm #ai #development #realpython
👉 @python_real
Если вы устали писать костыли для парсинга сырого текста от LLM, этот инструмент решает проблему изящно: вы задаете схемы через
BaseModel, а фреймворк сам берет на себя общение с нейросетью, валидацию и ретраи при ошибках формата.Что разбирается в статье:
• Структурированный вывод: Как заставить агента возвращать строго типизированные объекты вместо "простыни" текста.
• Использование инструментов (Tool Calling): Как с помощью простого декоратора
@agent.tool научить LLM вызывать ваши Python-функции (например, для запросов к API или БД).• Dependency Injection: Безопасный проброс контекста (сессий БД, настроек) в агенты и инструменты с проверкой типов через
RunContext.• Подводные камни: Честный разбор ограничений - как ретраи влияют на расход токенов, стоимость API и почему для масштабных проектов с кучей готовых интеграций всё еще может понадобиться LangChain или LlamaIndex.
Кому будет полезно?
Всем, кто хочет быстро прототипировать ИИ-фичи с минимальным количеством бойлерплейта и максимальным контролем над типами данных.
🔗 Читать туториал полностью: https://realpython.com/pydantic-ai/
#python #pydantic #llm #ai #development #realpython
👉 @python_real
❤1👍1
Вложенные циклы в Python
Вложенные циклы позволяют размещать один цикл внутри другого и тем самым выполнять повторяющиеся действия над несколькими последовательностями. Понимание этой концепции помогает писать более эффективный код, управлять сложными структурами данных и избегать проблем с читабельностью и производительностью.
Начало работы с вложенными циклами
В Python есть два основных типа циклов —
*
*
Вложенный цикл создаётся размещением одного цикла внутри другого:
Для каждой итерации внешнего цикла внутренний выполняется полностью.
Аналогия: часовая и минутная стрелки часов. Часовая проходит круг за 12 часов, минутная — за 1 час, но работают они совместно.
Практические примеры
Печать шаблонов
Таблица умножения
Суммирование элементов во вложенных списках
Парные комбинации без самих себя
Вложенный
Частые проблемы вложенных циклов
* Область видимости переменных. Не используйте одинаковые имена во внешнем и внутреннем циклах.
* Читаемость. Глубокая вложенность усложняет понимание кода.
* Производительность. Каждый дополнительный уровень увеличивает временную сложность (часто до
Оптимизация
*
* List Comprehension делает выражения компактнее, хотя не всегда улучшает производительность.
Вывод
Вложенные циклы — мощный инструмент для работы с многомерными данными и повторяющимися задачами. Однако злоупотребление ими ухудшает читаемость и скорость. Используйте их осознанно, оптимизируйте при помощи
https://realpython.com/nested-loops-python/
#python
👉 @python_real
Вложенные циклы позволяют размещать один цикл внутри другого и тем самым выполнять повторяющиеся действия над несколькими последовательностями. Понимание этой концепции помогает писать более эффективный код, управлять сложными структурами данных и избегать проблем с читабельностью и производительностью.
Начало работы с вложенными циклами
В Python есть два основных типа циклов —
for и while.*
for -цикл проходит по элементам последовательности (списка, диапазона и т. д.), когда количество итераций известно заранее.*
while -цикл выполняется, пока истинно заданное условие, и полезен, когда число итераций заранее не определено.Вложенный цикл создаётся размещением одного цикла внутри другого:
for outer_variable in outer_iterable:
for inner_variable in inner_iterable:
<body>
Для каждой итерации внешнего цикла внутренний выполняется полностью.
Аналогия: часовая и минутная стрелки часов. Часовая проходит круг за 12 часов, минутная — за 1 час, но работают они совместно.
for hour in range(24):
for minute in range(60):
print(f"{hour:02d}:{minute:02d}")
Практические примеры
Печать шаблонов
height = 6
sail_patterns = "*#-x+o"
for row in range(height):
pattern = ""
spacing = " " * (height - row)
for symbol in sail_patterns:
pattern += symbol * row + spacing
print(pattern)
Таблица умножения
for multiplicant in range(1, 11):
for multiplier in range(1, 4):
expression = f"{multiplicant:>2d} × {multiplier}"
product = multiplicant * multiplier
print(f"{expression} = {product:>2d}", end="\t")
print()
Суммирование элементов во вложенных списках
resource_donators = [
[8, 6, 3],
[9, 2, 7],
[4, 1, 5]
]
total_resources = 0
for planet in resource_donators:
for resource in planet:
total_resources += resource
print(total_resources) # 45
Парные комбинации без самих себя
players = ["Bonnie", "Mike", "Raj", "Adah"]
for player1 in players:
for player2 in players:
if player1 != player2:
print(f"{player1} vs {player2}")
Вложенный
while
while True:
word = input("Введите слово (exit — для выхода): ")
if word == "exit":
break
for letter in word:
print(letter)
Частые проблемы вложенных циклов
* Область видимости переменных. Не используйте одинаковые имена во внешнем и внутреннем циклах.
* Читаемость. Глубокая вложенность усложняет понимание кода.
* Производительность. Каждый дополнительный уровень увеличивает временную сложность (часто до
O(n²) и выше).Оптимизация
*
break и continue позволяют досрочно завершать цикл или пропускать ненужные итерации.* List Comprehension делает выражения компактнее, хотя не всегда улучшает производительность.
# Поиск "bacon" с break
for layer in blt_sandwich:
for ingredient in layer:
if ingredient == target:
print("Found bacon!")
break
if target in layer:
break
Вывод
Вложенные циклы — мощный инструмент для работы с многомерными данными и повторяющимися задачами. Однако злоупотребление ими ухудшает читаемость и скорость. Используйте их осознанно, оптимизируйте при помощи
break, continue и list comprehension, и никогда не забывайте о сложности алгоритма.https://realpython.com/nested-loops-python/
#python
👉 @python_real
👍2❤1
🐍 Как работают интерфейсы в Python и зачем они нужны?
В Python нет специального ключевого слова
Свежая и очень подробная статья от *Real Python* разбирает, как правильно реализовывать интерфейсы в Python. Вот два основных механизма:
🔹 Абстрактные базовые классы (ABCs)
Используем модуль
🔹 Протоколы (Protocols)
Современный подход структурной типизации с помощью
🦆 Duck Typing (Утиная типизация)
Куда же без нее! Python по своей природе динамичен: "если объект ходит как утка и крякает как утка, то это утка". ABC и Протоколы просто берут эту концепцию и делают ее безопаснее, позволяя использовать
Понимание интерфейсов помогает применять принципы объектно-ориентированного дизайна (SOLID) и писать код, который работает с различными типами данных без жесткой привязки к их конкретным реализациям.
https://realpython.com/python-interface/
#python
👉 @python_real
В Python нет специального ключевого слова
interface (как, например, в Java или C#), но это не значит, что мы не можем создавать надежные контракты для наших классов!Свежая и очень подробная статья от *Real Python* разбирает, как правильно реализовывать интерфейсы в Python. Вот два основных механизма:
🔹 Абстрактные базовые классы (ABCs)
Используем модуль
abc и декоратор @abstractmethod. Это строгий подход на основе наследования: если ваш дочерний класс не реализует все необходимые методы, Python выдаст ошибку TypeError еще на этапе создания объекта (instantiation), а не тогда, когда код упадет во время выполнения.🔹 Протоколы (Protocols)
Современный подход структурной типизации с помощью
typing.Protocol. Вашим классам вообще не нужно наследовать протокол — достаточно просто иметь нужные методы с правильными сигнатурами. Это идеально подходит для проверки статическими анализаторами кода (например, `mypy`).🦆 Duck Typing (Утиная типизация)
Куда же без нее! Python по своей природе динамичен: "если объект ходит как утка и крякает как утка, то это утка". ABC и Протоколы просто берут эту концепцию и делают ее безопаснее, позволяя использовать
isinstance() и issubclass() для проверки контрактов.Понимание интерфейсов помогает применять принципы объектно-ориентированного дизайна (SOLID) и писать код, который работает с различными типами данных без жесткой привязки к их конкретным реализациям.
https://realpython.com/python-interface/
#python
👉 @python_real
👍1
UV
Чрезвычайно быстрый менеджер пакетов и проектов на языке Python, написанный на Rust.
Создатели позиционируют его как замену pip, pip-tools и virtualenv. Это, кстати, те же разработчики, которые сделали линтер Ruff.
https://astral.sh/blog/uv
https://github.com/astral-sh/uv
#python
👉 @python_real
Чрезвычайно быстрый менеджер пакетов и проектов на языке Python, написанный на Rust.
Создатели позиционируют его как замену pip, pip-tools и virtualenv. Это, кстати, те же разработчики, которые сделали линтер Ruff.
https://astral.sh/blog/uv
https://github.com/astral-sh/uv
#python
👉 @python_real
👍2😁2
Реализация парсеров с Pylasu
В этой статье рассказывается, как реализовать парсеры на Python с использованием Pylasu и ANTLR. Пошагово:
1. Создадим грамматику ANTLR для простого языка программирования Slang и сгенерируем парсер.
2. Определим абстрактное синтаксическое дерево (AST) с помощью Pylasu и научимся строить его из дерева разбора ANTLR.
3. Интегрируем парсер с CLI-приложением для обработки кода Slang из строк и файлов, с выводом AST в формате JSON.
Полный код проекта доступен на GitHub. Вы можете экспериментировать, вносить улучшения и делиться идеями!
https://tomassetti.me/implement-parsers-with-pylasu/
#python
👉 @python_real
В этой статье рассказывается, как реализовать парсеры на Python с использованием Pylasu и ANTLR. Пошагово:
1. Создадим грамматику ANTLR для простого языка программирования Slang и сгенерируем парсер.
2. Определим абстрактное синтаксическое дерево (AST) с помощью Pylasu и научимся строить его из дерева разбора ANTLR.
3. Интегрируем парсер с CLI-приложением для обработки кода Slang из строк и файлов, с выводом AST в формате JSON.
Полный код проекта доступен на GitHub. Вы можете экспериментировать, вносить улучшения и делиться идеями!
https://tomassetti.me/implement-parsers-with-pylasu/
#python
👉 @python_real
👍2
Начиная с Python 3.0, при возникновении нового исключения внутри блока
Кроме того, вы можете явно указать причинное исключение, использовав конструкцию
#python
👉 @python_real
except перехваченное исключение автоматически сохраняется в атрибуте __context__ создаваемого исключения. В результате при выводе будут показаны оба исключения:
try:
1 / 0
except ZeroDivisionError:
raise ValueError('Zero!')
(most recent call last):
File "test.py", line 2, in <module>
1 / 0
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 4, in <module>
raise ValueError('Zero!')
ValueError: Zero!
Кроме того, вы можете явно указать причинное исключение, использовав конструкцию
raise … from. Тогда в атрибут __cause__ нового исключения будет помещено исходное:
division_error = None
try:
1 / 0
except ZeroDivisionError as e:
division_error = e
raise ValueError('Zero!') from division_error
(most recent call last):
File "test.py", line 4, in <module>
1 / 0
ZeroDivisionError: division by zero
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "test.py", line 8, in <module>
raise ValueError('Zero!') from division_error
ValueError: Zero!
#python
👉 @python_real
👍1
Метод
Имя поля используется для указания, какой именно аргумент должен быть подставлен:
Преобразование позволяет указать, что вместо
Спецификация формата задаёт, как значения будут представлены:
Эта спецификация может быть применена и к отдельному объекту с помощью функции
Функция
#python
👉 @python_real
format в Python для строк — мощный инструмент, поддерживающий множество возможностей, о которых вы, возможно, даже не знали. Каждый заменяемый плейсхолдер ({...}) может содержать три части: имя поля, преобразование и спецификацию формата.Имя поля используется для указания, какой именно аргумент должен быть подставлен:
>>> '{}'.format(42)
'42'
>>> '{1}'.format(1, 2)
'2'
>>> '{y}'.format(x=1, y=2)
'2'
Преобразование позволяет указать, что вместо
str() следует использовать repr() (или ascii()) при преобразовании объектов в строки:
>>> '{!r}'.format(datetime.now())
'datetime.datetime(2018, 5, 3, 23, 48, 49, 157037)'
>>> '{}'.format(datetime.now())
'2018-05-03 23:49:01.060852'
Спецификация формата задаёт, как значения будут представлены:
>>> '{:+,}'.format(1234567)
'+1,234,567'
>>> '{:>19}'.format(1234567)
' 1234567'
Эта спецификация может быть применена и к отдельному объекту с помощью функции
format (не метода str):
>>> format(5000000, '+,')
'+5,000,000'
Функция
format вызывает метод __format__ объекта, поэтому вы можете изменить его поведение для своих типов.#python
👉 @python_real
👍1
🐍 Интерфейсы в Python: когда
В Python нет привычных интерфейсов, как в Java или C#, но это не значит, что их нельзя использовать. На практике разработчики применяют несколько подходов — от обычного duck typing до абстрактных базовых классов (
Что важно знать:
🔹 Duck typing — классический подход Python. Если объект реализует нужные методы, значит, он подходит, независимо от наследования.
🔹 ABC (Abstract Base Classes) — позволяют явно определить набор обязательных методов. Если наследник не реализует их, создать экземпляр класса не получится.
🔹 Protocol — современный способ описывать интерфейсы без наследования. Особенно полезен при использовании статической проверки типов (
💡 Когда что использовать?
* Небольшие проекты — достаточно duck typing.
* Средние и крупные проекты —
* Современные кодовые базы с type hints — чаще всего лучший выбор
Если вы до сих пор считаете, что интерфейсов в Python нет, возможно, вы просто ещё не познакомились с
https://realpython.com/python-interface/
#python
👉 @python_real
ABC уже недостаточно?В Python нет привычных интерфейсов, как в Java или C#, но это не значит, что их нельзя использовать. На практике разработчики применяют несколько подходов — от обычного duck typing до абстрактных базовых классов (
abc) и современных Protocol из модуля typing. Что важно знать:
🔹 Duck typing — классический подход Python. Если объект реализует нужные методы, значит, он подходит, независимо от наследования.
🔹 ABC (Abstract Base Classes) — позволяют явно определить набор обязательных методов. Если наследник не реализует их, создать экземпляр класса не получится.
🔹 Protocol — современный способ описывать интерфейсы без наследования. Особенно полезен при использовании статической проверки типов (
mypy, Pyright и др.). Код становится гибче, а зависимости между классами — слабее. 💡 Когда что использовать?
* Небольшие проекты — достаточно duck typing.
* Средние и крупные проекты —
ABC помогает избежать ошибок реализации.* Современные кодовые базы с type hints — чаще всего лучший выбор
Protocol, который не требует наследования и отлично сочетается с IDE и статическими анализаторами. Если вы до сих пор считаете, что интерфейсов в Python нет, возможно, вы просто ещё не познакомились с
Protocol.https://realpython.com/python-interface/
#python
👉 @python_real
👍1