Код на салфетке
2.24K subscribers
751 photos
15 videos
2 files
793 links
Канал для тех, кому интересно программирование на Python и не только.

Сайт: https://pressanybutton.ru/
Чат: https://t.iss.one/+Li2vbxfWo0Q4ZDk6
Заметки автора: @writeanynotes

Реклама и взаимопиар: @Murzyev1995
Сотрудничество и др.: @proDreams
Download Telegram
Подготовили для вас разбор задачи "Что выведет этот код? №32".

Видео на YouTube.

Будем благодарны за ваши лайки и досмотр видео до конца, это важно для продвижения на YouTube. Спасибо!

Если у вас проблемы с YouTube, то посмотреть также можно:
- RuTube
- VK Видео
- Dzen

Текстовый разбор будет через 2 часа.
🔥21
Вчерашняя задача с виду простая, но рекурсия в ней может доставить неприятностей. Задачу решило 55% человек из 42-х проголосовавших.

Код задачи:
def recursive_sum(lst):  
if not lst:
return 0
return lst[0] + recursive_sum(lst[1:])


numbers = [1, 2, 3, 4, 5]
print(recursive_sum(numbers))



Разбор задачи
Создаём переменную numbers со списком чисел.
При помощи print() выводим вызов функции recursive_sum, передав в неё список чисел.

Объявляем функцию recursive_sum, принимающую аргумент lst.
Внутри функции, в блоке if проверяем, если переданный список пуст, то возвращаем 0.
В противном случае возвращаем сложение первого (нулевого) элемента списка и вызов этой же функции с новым списком в аргументах.


Правильный ответ: 15.

Процесс рекурсии.
Главная проблема рекурсии (не считая расходы на ресурсы) в том, что она не очевидна с первого взгляда и порой трудно поддаётся мысленной интерпретации.

Рассмотрим процесс выполнения recursive_sum:
1. Первый вызов функции: lst = [1, 2, 3 , 4, 5], возвращается lst[0] = 1.
2. Второй вызов функции: lst = [2, 3 , 4, 5], возвращается lst[0] = 2.
3. Третий вызов функции: lst = [3 , 4, 5], возвращается lst[0] = 3.
4. Четвёртый вызов функции: lst = [4, 5], возвращается lst[0] = 4.
5. Пятый вызов функции: lst = [5], возвращается lst[0] = 5.
6. Шестой вызов функции: lst = [], возвращается 0.

После того, как рекурсия дошла до конца, она начинает возвращать результаты сложения в обратном порядке:
1. 5 + 0 = 5, возвращается 5
2. 4 + 5 = 9, возвращается 9
3. 3 + 9 = 12, возвращается 12
4. 2 + 12 = 14, возвращается 14
5. 1 + 14 = 15, возвращается 15

Таким образом получаем ответ - 15
🔥21
Те, кто занимается парсингом сайтов ни раз сталкивались с проблемами "палящегося" Selenum'а или необходимости скачать новый вебдрайвер для браузера, также Selenum достаточно медленный. Решение всех этих проблем предлагает библиотека Nodriver.

Nodriver — это библиотека для высокопроизводительного веб-скрапинга и автоматизации, не использующая традиционные методы WebDriver или Selenium. Она обходит защитные меры, такие как Captcha и Cloudflare, напрямую взаимодействуя с браузером и поддерживая асинхронные операции для повышения скорости. Библиотека проста в использовании благодаря продуманным настройкам по умолчанию, но также позволяет продвинутым пользователям настраивать её под свои задачи.

Репозиторий библиотеки.

Установка библиотеки:

Для установки достаточно выполнить команду:
pip install nodriver


Пример получения изображений из Яндекс Картинок:
import asyncio
from pathlib import Path

import httpx
import nodriver as uc


async def main():
url = 'https://yandex.ru/images/search?from=tabbar&text=котики&isize=eq&iw=1920&ih=1080'

browser = await uc.start()
page = await browser.get(url)

elems = await page.select_all('.JustifierRowLayout-Item')

for i, elem in enumerate(elems):
a = await elem.query_selector('a')
image_page = await browser.get(f"https://yandex.ru{a.attrs.get('href')}", new_window=True)
image = await image_page.select('.MMImage-Origin')
file_resp = httpx.get("https:" + image.attrs.get('src'))
with open(Path('downloads') / f"{i}.png", 'wb') as file:
file.write(file_resp.content)
await image_page.close()


asyncio.run(main())


Создаём асинхронную функцию main.
В ней указываем url страницы, с которой начнём парсинг.
Затем создаём экземпляр браузера и открываем в нём страницу.
Ищем нужные элементы, в данном случае содержащие превьюшки изображений.
Далее, итерируясь по полученным элементам, находим в них ссылки на страницы изображений и открываем в новом окне.
Затем, находим само изображение и скачиваем его при помощи httpx.

Данный код всего лишь пример работы с библиотекой, которая упростит жизнь разработчику парсеров.

P.S. Напишите в комментарии, нужны ли гайды по парсингу?
🔥8👍2
Сегодня исполнилось 11 лет с запуска Telegram, платформы, которая не только изменила мир мессенджеров для пользователей, но и предоставила обширные возможности для разработчиков.

В честь одиннадцатилетия Telegram прдоставил крупное обновление BotAPI 7.9, направленное на поддержку авторов контента.

В этом посте разберём те части обновления, которые касаются разработчиков. Полностью прочитать о представленных нововведениях можно по ссылке.


Звёздные реакции
Появилась возможность отправлять "Звёздные реакции" к постам в каналах - это способ отблагодарить автора контента используя Telegram Stars. Также, в меню звёздной реакции отображается "Список лидеров", подписчиков отправивших больше всего звёзд к конкретному посту.

Включить звёздные реакции на сообщения в канале можно в меню Настройки канала > Реакции > Включить платные реакции.


В API бота добавлена поддержка платных реакций и новый класс ReactionTypePaid, определяющий "звёздную реакцию".


Подписка на канал за Telegram Stars
С сегодняшнего дня, можно создавать пригласительные ссылки на канал с указанием ежемесячной платы в звёздах. Это позволяет авторам контента создать закрытый канал и предоставлять к нему доступ по подписке.

Чтобы сгенерировать ссылку для платной подписки на канал, перейдите в Настройки канала > Тип канала > Управление приглашениями > Создать ссылку и включите опцию Ежемесячная плата.


Также, такие ссылки может создавать и бот. Для этого были добавлены следующие API-методы и поля:
- Метод createChatSubscriptionInviteLink - Позволяющий ботам создавать пригласительные ссылки с подпиской.
- Метод editChatSubscriptionInviteLink - Позволяет ботам редактировать название уже имеющейся пригласительной ссылки.
- Поле until_date в класс ChatMemberMember - Необязательное поле для объекта класса, указывающее на то, имеется ли у подписчика канала платная подписка.


Публикация платного медиаконтента ботами
Изначально, платный контент за "Звёзды", можно было публиковать только в каналах, однако, теперь их могут отправлять и боты. Это позволит многим авторам контента продавать эксклюзивные фото и видео, а также предлагает новый способ монетизации сервиса.

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

В API бота добавили:
- Возможность отправки платного медиа в любой чат
- В метод sendPaidMedia добавлено поле business_connection_id для отправки платного контента в чат, используя бизнес аккаунт.
- В класс TransactionPartnerUser добавлено поле paid_media для платежей связанных с платным контентом.


Суперканалы
Сообщения в канале публикуются от имени канала, максимум, что можно было сделать раньше - это добавить подпись с именем автора сообщения. Теперь можно включить отправку сообщений непосредственно от своего имени или имени другого своего канала.

Чтобы превратить канал в суперканал, перейдите в Настройки канала > Администраторы и включите «Подписывать сообщения» и «Показывать профили авторов».


В API бота добавили поддержку Суперканалов, позволяющую получать сообщения из канала отправленные от лица пользователя или другого канала.

Поддержать проект на Boosty
Поддержать проект в Telegram

#Новости #Telegram #Stars #BotAPI #Telegram_Stars #Код_на_салфетке #Обновление #Бот #Telegram_бот
116🔥2
Веб-сервер Caddy - Альтернатива NGINX и Apache
Автор: Иван Ашихмин

В этом посте познакомимся с веб-сервером Caddy, современной альтернативой NGINX и Apache с автоматическим получением сертификатов для сайта.


Читать пост в Telegram

Пост на сайте
Поддержать проект на Boosty
Поддержать проект в Telegram

#Lets_Encrypt #гайды #полезные_инструменты #docker #docker_compose #apache #хотлинкинг #nginx #caddy #TLS #веб_сервер #сертификаты
145👍2🔥1
Приветствуем!

Продолжаем рубрику "Вопросы и ответы"!

В течение недели вы в комментариях к этому посту можете задавать различные вопросы нашей команде. Вопросы могут быть о чём угодно (в рамках разумного): о постах, о Python, о разработке в целом.

Ровно через неделю мы подготовим пост с ответами на появившиеся вопросы.

Также у нас есть чат, в котором тоже можно задавать вопросы и просто общаться)
🔥2
Приветствую!

Сегодня мы погружаемся в увлекательный мир фантастики и истории. Эта картина рассказывает о группе современных молодых людей, которые, занимаясь поисками артефактов времён Великой Отечественной войны, неожиданно перемещаются в прошлое и оказываются в самом центре боевых действий. Фильм захватывает дух и заставляет задуматься о ценностях, которые мы часто принимаем как должное. Устраивайтесь поудобнее, включайте фильм и наслаждайтесь просмотром!

Фильм: Мы из будущего

Год: 2008

Компания молодых парней по прозвищу Череп, Чуха и Спирт во главе с бывшим студентом-историком Борманом нашли себе оригинальный способ заработка – откапывать и продавать военные реликвии. Им нет дела до прошлого своей страны, их интересуют только деньги, которые можно выручить на черном рынке. Отрыв очередной «клад», парни обнаруживают солдатские книжки со своими фамилиями и фотографиями. Но на этом невероятные сюрпризы только начинаются.

Приятного просмотра!

P.S. Пиратских ссылок на фильмы больше не будет
🔥2
Что выведет код с изображения? №33
Anonymous Quiz
11%
14
6%
7
39%
RecursionError
28%
10
17%
28
👍1🔥1
Что выведет этот код? №33
🔥1
Вчерашняя задача была не простой, на первый взгляд. Бинарные деревья сложно даются многим, а данную задачу решило 29% из всего 14ти ответивших.

Код задачи:
from dataclasses import dataclass


@dataclass
class Node:
value: int
left: "Node" = None
right: "Node" = None


def sod(root, depth=0):
if root is None:
return 0
return depth + sod(root.left, depth + 1) + sod(root.right, depth + 1)


root_node = Node(
value=1,
left=Node(value=2, left=Node(4), right=Node(5)),
right=Node(value=3, left=Node(6), right=Node(7))
)

print(sod(root_node))



Разбор задачи
Пойдём сверху вниз. Сперва создаём датакаласс Node, описывающий узел бинарного дерева. Применение датакласса описано в посте "[AIOgram3 5.1. Создание структуры](https://pressanybutton.ru/post/telegram-bot-na-aiogram3/aiogram3-51-sozdanie-struktury/)".
В классе прописываем три поля:
1. value - числовое значение хранящееся в узле.
2. left - указание на дочерний узел в левой части дерева.
3. right - указание на дочерний узел в правой части дерева.
Обратите внимание, поля left и right являются объектами этого же класса Node и для указания типа данных используются двойные кавычки, поскольку мы не можем явно указать внутри класса, что он используется "сам в себе".

Далее идёт функция sod, принимающая аргументы:
- root - корневой узел.
- depth - глубина относительно начала дерева, по умолчанию 0.
Поскольку функция рекурсивная, необходимо в самом начале прописать условие выхода из рекурсии. Прописываем блок if, проверяющий, что переданный корень существует, если же вместо него пришёл None, возвращаем 0.
Если выхода из функции не произошло, то возвращаем сумму текущей глубины с глубинами дочерних узлов в рекурсивном вызове.

После класса и функции, создаём переменную root_node, в которой определяем экземпляр класса Node с рядом дочерних узлов.

В самом конце выводим результат вызова функции sod в терминал.

Правильный ответ: 10.


Что это за дерево такое?
Теперь разберёмся, какое дерево у нас получилось. Мы построили классическое бинарное дерево. В нашем случае, корневой узел содержит значение 1, его левый потомок - узел с значением 2, правый - 3, и так далее. Каждый узел может иметь до двух потомков: left и right. Графически дерево можно изобразить следующим образом:

       1
/ \
2 3
/ \ / \
4 5 6 7


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


Процесс вычисления суммы глубин.
Теперь вернёмся к функции sod. В процессе её выполнения мы фактически проходим по всем узлам дерева, начиная с корня. На каждом уровне прибавляем текущее значение глубины к результату рекурсивного вызова для левого и правого потомков.


Пройдемся по дереву:
1. Стартуем с корня (1). Глубина 0.
2. Переходим на левую ветку: узел 2, глубина 1.
3. Снова идём влево: узел 4, глубина 2. Узел не имеет потомков, возвращаем 2.
4. Возвращаемся к узлу 2, идём вправо: узел 5, глубина 2. Узел не имеет потомков, возвращаем 2.
5. Возвращаемся к узлу 1, обрабатываем правую ветку: узел 3, глубина 1.
6. Идём влево: узел 6, глубина 2. Узел не имеет потомков, возвращаем 2.
7. Возвращаемся к узлу 3, идём вправо: узел 7, глубина 2. Узел не имеет потомков, возвращаем 2.

Суммируем результат:
- Глубина 0 (узел 1): 0
- Глубина 1 (узлы 2 и 3): 1 + 1 = 2
- Глубина 2 (узлы 4, 5, 6, 7): 2 + 2 + 2 + 2 = 8

Общая сумма глубин = 0 + 2 + 8 = 10.

Вот и весь процесс. В итоге мы получили ответ 10, который и является суммой всех глубин узлов в этом бинарном дереве.


Заключение
Таким образом, задача оказалась не такой сложной, как показалось на первый взгляд, особенно если разбить её на части. Основной вызов здесь – правильно понять, как работает рекурсия и как она взаимодействует с каждым узлом в дереве.
244🔥3
При работе с различными API-запросами, чаще всего на ум приходит библиотека requests. Она отлично выполняет свою функцию, однако, она не поддерживает асинхронное выполнение. На замену requests пришла новая библиотека httpx.

Пример выполнения GET-запроса:
response = httpx.get("https://reqres.in/api/users/2")
print(response.status_code)
print(response.json())


В этом примере выполнен базовый GET-запрос. Метод .get() возвращает объект Response, который содержит статус ответа, заголовки и данные ответа.


Пример выполнения асинхронного POST-запроса:
async def fetch_data():
async with httpx.AsyncClient() as client:
response = await client.post(
"https://reqres.in/api/users", data={"name": "Napkin", "job": "Author"}
)
print(response.status_code)
print(response.json())


asyncio.run(fetch_data())


В этом примере мы открыли асинхронный клиент в контекстном менеджере для выполнения запроса. В метод .post(), также передали аргумент data, содержащий словарь данных.


Пример выполнения stream-запроса:
async def fetch_data():
async with httpx.AsyncClient() as client:
async with client.stream(
"POST",
"https://api.openai.com/v1/chat/completions",
json={
"model": "gpt-4o-mini",
"messages": [
{"role": "system", "content": "You are a assistant."},
{"role": "user", "content": "Hello!"},
],
"stream": True,
},
headers={
"Authorization": "Bearer <token>"
},
) as response:
async for chunk in response.aiter_text():
yield chunk


async def main():
async for data in fetch_data():
print(data)


asyncio.run(main())


Этот пример показывает, как httpx может использоваться для выполнения запросов в режиме "стриминга".
5🔥5
108❤‍🔥3🔥3
Channel photo updated
Сравнение hash map С/C++ с dict Python (часть 1)
Автор: Eugene Kaddo

Данная статья расскажет чем отличаются hash map C/C++ от dict Python и как их реализовать.


Читать пост в Telegram

Файлы к посту, можно получить в боте по коду: 301030

Пост на сайте
Поддержать проект на Boosty
Поддержать проект в Telegram

#Python #Сравнение_Python_и_C #C #C++ #hash_map #hash_table #dict
🔥7👍1
Записали новое видео, посвящённое выводу и лимитам Telegram Stars.
В видео поменяли оформление, расскажите, как вам?

Смотреть на YouTube.

Будем благодарны, если досмотрите видео до конца и поставите лайк. Это покажет YouTube, что видео интересное и, что его следует рекомендовать. Спасибо!

А если у вас проблемы с доступом к YouTube, то видео можно посмотреть и на других платформах:

- Ссылка на VK Video
- Ссылка на Dzen
- Ссылка на RuTube
- Ссылка на "Платформу"
🔥102👍1
Приветствую всех, друзья!

Пятница наступила, а это значит, что настало время для нашего еженедельного кинопоста. Сегодня я рад представить вам захватывающий триллер по рекомендации одного из наших подписчиков.

Этот фильм погружает нас в мир хакеров и цифровых технологий, где границы между реальностью и виртуальностью становятся всё более размытыми. Главный герой, молодой и талантливый хакер Бенджамин, стремится выйти из тени и стать известным. Но его путь к славе оказывается не таким простым, как он предполагал.

Фильм: Кто я

Год: 2014

"Кто я" — это не просто триллер, это глубокий взгляд на современное общество и его зависимость от технологий. Фильм поднимает важные вопросы о безопасности, анонимности и личной ответственности в цифровую эпоху. Приготовьтесь к напряжённому и увлекательному просмотру, который заставит вас задуматься о том, кто мы на самом деле в этом мире информации и иллюзий.

Устраивайтесь поудобнее, включайте фильм и наслаждайтесь просмотром!
👍4🔥31
Что выведет код? №34
🔥51🥰1
Записали видео с разбором задачи. Текстовая версия будет через пару часов.

Смотреть на YouTube.

Будем благодарны, если досмотрите видео до конца и поставите лайк. Это покажет YouTube, что видео интересное и, что его следует рекомендовать. Спасибо!

А если у вас проблемы с доступом к YouTube, то видео можно посмотреть и на других платформах:

- Ссылка на VK Video
- Ссылка на Dzen
- Ссылка на RuTube
- Ссылка на "Платформу"
🔥6👍1👏1