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

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

Реклама и взаимопиар: @Murzyev1995
Сотрудничество и др.: @proDreams
Download Telegram
Вчера мы опубликовали коротенькую, но интересную задачу. Верно ответили 43% из 37-ми человек.

Код задачи:
x = b'1001'
y = b'1010'

print(x + y)



Разбор задачи
Задача короткая и разбор будет таким же.

Создаём две переменные x и y, в которые помещаем две байтовые строки (byte string).

Далее в функции print() выводим результат конкатенации строк.

Думаю, на этом моменте уже стало понятно, почему правильный ответ b'10011010'.

Про строки байт.
Байтовые строки - это последовательность необработанных байт от 0 до 255, интерполируемая Python как строка, но со специальным литералом b"", в то время как обычные строки, это набор символов в определённой кодировке (обычно это UTF-8).

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

Превратить обычную строку в байтовую можно двумя способами:
1. Добавив перед кавычками литерал b - b"строка_текста".
2. Использовав метод строки .encode("кодировка") с указанием желаемой кодировки - "строка_текста".encode("utf8"). Преобразовать байтовую строку с текстом обратно можно использовав метод строки .decode("utf8").

Байтовые строки, практически ничем не отличаются от обычных. Им доступны всё те же методы и функции. Такие как: доступ к элементам по индексу, конкатенация, .split(), "".join() и другие.

Понимание работы байтовых строк особенно полезно при веб-разработке, поскольку все данные пересылаемые через интернет - являются набором байт. Данные кодируются в байты, пересылаются, затем декодируются, согласно требуемому формату данных.
🔥31
Приветствуем.

Сделали Shorts к задаче:
https://youtube.com/shorts/sSLH46uESzQ?feature=share

Будем благодарны за лайк и комментарий!
🔥3
Приветствую!

Быстро же летит время. Ровно год назад я создал этот канал и начал писать статьи про Django и AIOgram. В процессе появился сайт и чат. Я тогда и не подозревал, что вас будет больше 500 человек, а на сайте больше 100 посетителей ежедневно.
Практически сразу ко мне присоединились единомышленники. Без их помощи и поддержки всего этого бы не было. Мы, конечно, бывает, ворчим друг на друга (в основном я на всех или все на меня), но останавливаться не собираемся.
Мы постоянно учимся и не только программированию, о котором рассказываем, но и ведению канала, взаимодействию с вами, организации процессов - это всё сложно для непосвящённых вроде нас.

Благодарю команду за участие в этом авантюрном проекте. Авторов, пишущих для вас у нас. Вас - аудиторию, кто ставит реакции, пишет комментарии. Бустеров, а теперь ещё и тех, кто задонатил в боте - без вас, было бы нечем оплачивать сервер для сайта.


Передаю слово команде:

Большакова Кристина:
Год! Уже год! И правда быстро!

Данному каналу невероятно повезло! Здесь прекрасная команда администраторов, замечательные и интересные люди. Подписчики - удивительные и душевные люди!

Пусть канал продолжает расти и развиваться. А душевность остается навсегда!

С Днем Рождения, милый канал!


Лебедев Андрей:
Большое спасибо Ване и Кристине, которым этот канал обязан своим появлением. Первому - за целеустремленность и любопытство, а второй - за упорство и терпение.

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

Поздравляю всех нас с днём рождения канала!


Мурзыев Артур:
Не передать словами, каково это быть свидетелем того, как идея претворяется в жизнь. Как мысль материализуется упорством, бессонными ночами, трудом и потом. Видеть вживую, как общие интересы обьединяют людей со всей страны и не только.

Огромная благодарность всем подписчикам и подписчицам. Благодаря вам канал живёт, растёт и совершенствуется.
🎉18🔥32👍1
Найдите ошибку в коде ниже и исчерпывающим образом объясните ее в комментариях.

#python #код_на_салфетке #найди_ошибку
🤔4🔥1
Третья задача была довольно простой, если проявить внимательность.

Код задачи:
distance = {"home_school": 3, "school_shop": 2, "shop_home": 1}  

speed = {"runing": 15, "jogging": 10, "walking": 5, "crawling": 3}

time = (
distance.get("home_school", 0) / speed.get("jogging", 0)
+ distance.get("school_shop", 0) / speed.get("running", 0)
+ distance.get("shop_home", 0) / speed.get("walking", 0)
)

print(time)


Разбор задачи.
Вся суть задачи сводится к пониманию работы метода .get() у словарей.
Дело в том, что метод принимает один обязательный элемент - ключ, по которому ищет значение в словаре, и стандартное значение, которое возвращает, если ключ не был найден. Если стандартное значение не указано, возвращается None.

Первым на ошибку указал в комментариях - MAG.

Если внимательно пройтись по операторам в переменной time и ключам словаря, станет очевидно, что в словаре speed нет ключа running, а есть runing. Поэтому метод .get() вернёт установленное стандартное значение - 0.

Получается, что в одной из частей выражения мы делим на ноль, в связи с чем получаем ошибку DivisionByZero.
🔥41
Обновление библиотеки - AIOgram 3.8.0
Автор: Иван Ашихмин

Вышла новая версия библиотеки AIOgram 3.8.0.

Установить новую версию можно выполнив команду:

pip install -U aiogram


Главное.
- Добавлена утилита для безопасной десериализации любого объекта или метода Telegram в JSON-совместимый объект (dict). (Читать подробнее).
🔥1
- Добавлена полная поддержка Bot API 7.5:
- Добавлены классы aiogram.types.star_transactions.StarTransactions, aiogram.types.star_transaction.StarTransaction, aiogram.types.transaction_partner.TransactionPartner и aiogram.types.revenue_withdrawal_state.RevenueWithdrawalState, содержащие информацию о транзакциях Telegram Stars в боте.
- Добавлен метод aiogram.methods.get_star_transactions.GetStarTransactions для получения списка всех транзакций Telegram Stars в боте.
- Добавлена поддержка колбэк (callback) кнопок в aiogram.types.inline_keyboard_markup.InlineKeyboardMarkup для сообщений отправленных с использованием бизнес-аккаунта.
- Добавлена поддержка колбэк запросов (callback queries) для сообщений, отправленных с использованием бизнес-аккаунта.
- Добавлен аргумент business_connection_id в методы aiogram.methods.edit_message_text.EditMessageText, aiogram.methods.edit_message_media.EditMessageMedia, aiogram.methods.edit_message_caption.EditMessageCaption, aiogram.methods.edit_message_live_location.EditMessageLiveLocation, aiogram.methods.stop_message_live_location.StopMessageLiveLocation и aiogram.methods.edit_message_reply_markup.EditMessageReplyMarkup, позволяющий редактировать сообщения, отправленные с использованием бизнес-аккаунта.
- Добавлен аргумент business_connection_id в метод aiogram.methods.stop_poll.StopPoll, позволяет остановить опросы которые он делает от имени бизнес-аккаунта.


Исправления.
- Увеличено время жизни кэша DNS в сессии aiohttp как обходной путь для проблем с разрешением DNS в aiohttp.


Улучшение документации:
- Исправлен раздел MongoStorage в документации путем добавления дополнительной зависимости в конфигурацию ReadTheDocs.
- Добавлена информация об изменениях зависимостей в руководство по миграции с версии 2.x на 3.x.


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

#перевод #список_изменений #aiogram #telegram #новая_версия #telegram_бот #bot_api #changelog
🔥4
Сравнение array C и list Python
Автор: Arduinum628

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

Итак, продолжим. В предыдущей статье "Сравнение интерпретатора Python и компилятора C" я затрагивал вскользь темы array и list, а также циклов while. Поэтому в данной статье я сравню array (массив) из языка C и list (список) из языка Python, обход которых я сделаю на цикле while. Давненько я не писал статьи и даже очень соскучился по этому процессу. Так что приступаю к продолжению этой интересной и захватывающей рубрики.
🔥2
Сравнение array и list
Для начала начнём со знакомого многим питонистам list (список) из языка Python. Список - это неограниченная по размеру упорядоченная коллекция произвольных объектов. Для начала давайте создадим список в Python.


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

Я создал список и назвал его list_example так как он не будет привязан к конкретным данным или назначению. Давайте запустим в IDE и посмотрим что он выдаст в эмуляторе terminal на моём Debian. Я перешёл с Kubuntu на Debian 12, но различий между двумя этими системами для демонстрации кода не будет. При нажатии на кнопку run python file в IDE VS Code видим следующий вывод.

В terminal


[1, 2, 3, 4, 5]

Функция print из строки print(list_example) печатает нам содержимое списка [1, 2, 3, 4, 5], в котором находятся числа. Прежде чем перейти к написанию кода с аналогичным функционалом на C давайте разберёмся что такое array.

Массив, или array, в языке C - это структура данных, которая позволяет хранить последовательности элементов одного типа. Это определение уже намекает нам на то, что в массиве на языке C не может быть разных типов данных. Чуть позже я объясню почему, а сейчас создадим массив, похожий на список, что я писал выше на Python.


#include <stdio.h>
#include <string.h>
int main(){
int array_example[] = {1, 2, 3, 4, 5};
char buffer[100];
sprintf(
buffer,
"[%d, %d, %d, %d, %d]",
array_example[0],
array_example[1],
array_example[2],
array_example[3],
array_example[4]
);
printf("%s\n", buffer);
return 0;
}

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

В terminal


$ gcc ./array_c.c -o array_c
$ ./array_c
[1, 2, 3, 4, 5]

После компиляции и запуска данного кода мы видим тот же результат, что и в коде на Python в эмуляторе terminal [1, 2, 3, 4, 5]. Давайте разберёмся, что мы вообще такое написали на С. Строка #include <string.h> включает заголовочный файл для компилятора, который нужен для работы со строками. В нашем случае заголовочный файл нужен, чтобы использовать функцию sprintf для формирования строки. Из предыдущей статьи вы помните, что строка int array_example[] = {1, 2, 3, 4, 5}; создаст массив целых чисел. Прошу обратить внимание, что вы не можете класть туда любые типы данных как это делается в языке Python! Компилятору явно указывается, что в массиве у нас тип данных int - целое число. Давайте взглянем на примере, что будет если положить в массив тип данных char или символ строки. При форматировании укажем %s спецификатор формата для char. Для этого давайте слегка поправим код.


#include <stdio.h>
#include <string.h>
int main(){
int array_example[] = {1, 2, 3, 4, "r"};
char buffer[100];
sprintf(
buffer,
"[%d, %d, %d, %d, %s]",
array_example[0],
array_example[1],
array_example[2],
array_example[3],
array_example[4]
);
printf("%s\n", buffer);
return 0;
}

Ещё раз компилируем и запустим код в terminal.


$ gcc ./array_c.c -o array_c
array_c.c: In function ‘main’:
array_c.c:5:40: warning: initialization of ‘int’ from ‘char *’ makes integer from pointer without a cast [-Wint-conversion]
5 | int array_example[] = {1, 2, 3, 4, "r"};
| ^~~
array_c.c:5:40: note: (near initialization for ‘array_example[4]’)
🔥2
Предупреждение нам говорит о том, что мы пытаемся добавить char символ к int массиву что сделать невозможно. Это сломает вашу программу так как компилятор ожидает только int тип в массиве. Перепишем код обратно на тот что был и снова перекомпилируем. Просто повторите предыдущий рабочий код, что был до изменений, и заново запустите команду компиляции. Всё должно работать как раньше.

Давайте разберём оставшиеся строки кода. Строка char buffer[100]; создаёт массив char из 99 символов и 1 символ конца строки \0. Это нужно для хранения символов строки char. Цифра 100 на самом деле не количество символов, а размер массива в байтах. Если вы введёте printf("%d\n", sizeof(char)); в свой код, то увидите что 1 char символ занимает 1 байт. Для сравнения 1 int число занимает 4 байта. Поэтому можно легко рассчитать какой размер буфера вам нужен для хранения массива char. Размер 100 байт в нашем случае очень избыточен, поэтому рассчитаем точный размер 5 * 1 + 1 = 6. Количество символов умножаем на вес одного в байтах и прибавляем 1 байт для символа конца строки. Квадратные скобки и запятые в нашем буфере не хранятся. Таким образом мы экономим 94 байта на компьютере. Программы на C требуют, чтобы вы следили за размером, который занимают ваши данные. Немного непривычно после языка Python, не так ли? На самом деле в Python тоже нужно думать о размере данных, но из-за того что он динамический и много прощает, следить за этим гораздо сложнее. Далее в функцию sprintf мы кладём наш буфер для хранения char, форматируем строку "[%d, %d, %d, %d, %d]" и для каждого спецификатора формата %d берём каждое число по индексу из массива. Далее функция sprintf заполнила наш buffer данными char в результате чего получился массив символов, последовательность которых образует строку. Ну и в конце выводим нашу строку в terminal (эмулятор терминала). В Python функция print сама выводила нам содержимое списка, а в C нам пришлось для этого форматировать строку. Возможности языка C и возможности Python разные и иногда в C просто нет простого решения. Давайте попробуем на Python написать близкий внешне вариант. Для этого перепишем наш Python код. Напишу два варианта: более старый и более новый и быстрый.


from typing import List
list_example: List[int] = [1, 2, 3, 4, 5]
str_list = '[%d, %d, %d, %d, %d]' % (list_example[0], list_example[1], \
list_example[2], list_example[3], list_example[4])
print(str_list)

Первый вариант использует оператор %, который более родственный языку C. Обратите внимание: я использую аннотацию типов List[int], показывая, что у нас должен быть тип данных list с числами int типа внутри. Это работает на уровне соглашения между разработчиками и не влияет на саму работу кода. И если туда добавить другой тип данных естественно ничего не сломается. Результатом в переменной str_list будет отформатированная оператором % строка [1, 2, 3, 4, 5], которую мы потом выводим в terminal с помощью функции print.


from typing import List
list_example: List[int] = [1, 2, 3, 4, 5]
str_list = f'[{list_example[0]}, {list_example[1]}, {list_example[2]}, '\
f'{list_example[3]}, {list_example[4]}]'
print(str_list)

Второй вариант использует f строки, которые работают быстрее оператора % и использование которых имеют более короткий и удобный синтаксис. Результат будет тот же самый что и в примере с оператором %. Если ваша Python версия поддерживает f строки, рекомендую использовать именно их.
🔥2
Далее я хочу пройти по списку и массиву с помощью цикла while и вывести каждое из чисел в списке. Довольно просто и банально, но моя цель - показать отличия Python от C, а не усложнять сам код. После того как я покажу вам основы, буду ставить задачи посложнее и писать более сложный код. Для начала напишем код на более простом языке Python.


from typing import List
list_example: List[int] = [1, 2, 3, 4, 5]
i = 0
while i <= list_example.index(list_example[-1]):
print(list_example[i])
i += 1

У меня получился довольно простой и элегантный вариант в версии Python. Когда я пишу на Python, я не пытаюсь усложнить задачу, а наоборот - стараюсь пользоваться его средствами для упрощения себе работы. В данном случае я использую функцию index для удобства. У нас есть переменная i для индекса, по которому нужно брать элементы из списка list_example. Строка while i <= list_example.index(list_example[-1]): говорит нам о том, что мы не выйдем из цикла while пока значение переменной i не будет равно последнему индексу списка. Далее выводим данные на экран в строке print(list_example[i]). После чего прибавляем на единицу переменную индекса i . Давайте запустим наш код в VS Code и взглянем на результат.


1
2
3
4
5

Видим, что наш код отработал как нужно - вывел все числа списка. После чего цикл while завершился. Пришло время написать код с похожим функционалом на C.


#include <stdio.h>
int main(){
int array_example[] = {1, 2, 3, 4, 5};
int i = 0;
int i_end = sizeof(array_example) / sizeof(array_example[0]) - 1;
while (i <= i_end){
printf("%d\n", array_example[i]);
++i;
}
return 0;
}

Давайте взглянем на наш C код и на отличия в работе его логики. У нас имеется переменная для индекса int i = 0;. Строка получения длины списка вам уже известна из предыдущей главы и единственное здесь отличие - мы отнимаем единицу. Это нужно для того, чтобы получить последний индекс списка. Строка int i_end = sizeof(array_example) / sizeof(array_example[0]) - 1; успешно получит число 4. Далее идёт условие работы цикла: while i <= i_end работает аналогично примеру из Python. Строка printf("%d\n", array_example[i]); выведет число из списка в terminal. В конце ++i; мы прибавляем единицу к переменной индекса i. Вот тут хочу остановиться поподробнее. Дело в том, что есть два варианта: ++i и i++. Первый вариант ++i это префиксная форма и она сначала увеличивает значение, а потом возвращает его. Второй вид i++ это суффиксная форма, которая сначала вернёт текущее значение, а потом увеличит его. Будьте внимательны при использовании, у них будут разные результаты и может быть ошибка в логике программы.
Теперь давайте скомпилируем и запустим программу.


$ gcc array_c.c -o array_c
$ ./array_c
1
2
3
4
5

Всё хорошо, программа отработала как нужно и вывела нам каждое число из массива.


Бонус
Как известно, в Python, увы, нет встроенного в язык типа данных array, но зато есть встроенный модуль array, который обеспечивает схожую функциональность. Давайте посмотрим как он работает на примере.


arr = array('i', [0]*5)
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5
print(arr)
print(arr[0])

Первая строка arr = array('i', [0]*5) создаёт аналог массива (по функциональности) и заполняет его пятью элементами нулями, i указывает, что это массив с данными int типа. Далее, как и в обычном list, мы присваиваем значение по индексу arr[0] = 1 и т.д. Давайте запустим код и убедимся, что всё работает.
🔥21
array('i', [1, 2, 3, 4, 5])
1

Мы видим, что у нас создался объект array, который заполнился данными. Далее мы выводим элемент цифру 1 по индексу 0. Согласитесь, не очень удобно заполнять нулями, а потом присваивать по каждому индексу значения? Мы можем сразу заполнить массив нужными значениями, уменьшив этим количество строк кода. Заодно давайте добавим новый элемент в массив, а так же добавим другой тип данных.


arr = array('i', [1, 2, 3, 4, 5])

print(arr)
arr.append(6)
print(arr)
arr.append('number')
print(arr)

Запустим наш новый код в terminal.


array('i', [1, 2, 3, 4, 5])
array('i', [1, 2, 3, 4, 5, 6])
Traceback (most recent call last):
File "/home/arduinum628/Документы/Helper_for_programmer/Articles/Code/Код из статьи array C list Python/list_python.py", line 43, in <module>
arr.append('number')
TypeError: 'str' object cannot be interpreted as an integer

При запуске нашего кода мы видим, что у нас создался такой же массив как и в примере выше. Далее мы добавили новый элемент с помощью метода append. Потому что размер array динамический в данной библиотеке. Обратите внимание что в языке C массив имеет фиксированный размер и выйти за его размеры у вас не получиться. Таким образом мы ограничиваем ресурсы нашего ПК в языке C. В Array мы получили фиксированную типизацию для массива указав i (int). Поэтому мы получили ошибку при добавлении в него типа данных str строки number. Также возможности встроенной библиотеки array позволяют удалять элемент по индексу del arr[0].


Заключение
- Узнали, чем отличается array (массив) в C от list (список) в Python;
- Научились работать с bufer для хранения символов типа данных char для строк;
- Посмотрели как работает цикл while на обоих языках;
- Затронули тему аннотации типов в Python;
- Бонусом посмотрели встроенный в Python модуль array, который может создавать подобие массива;




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

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

#Python #Сравнение_Python_и_C #C #while #цикл #Python_array #массив_в_Python
🔥3
Приветствуем!

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

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

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

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

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

Фильм: Унесённые призраками

Год: 2001

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

https://www.sspoisk.ru/film/370/

Приятного ппросмотра!
🔥5
Что выведет этот код? №27
Вчерашняя задача была короткой, но интересной и как оказалось сложной. Правильно ответили всего 9 человек из 33-х, что равно 27%.

Код задачи:
numbers = [1, 2, 3]
numbers.append(*[4, 5])

print(numbers)



Разбор задачи
Сперва пройдёмся по строкам.

Сначала объявляем переменную numbers и присваиваем ей список чисел [1, 2, 3].

Затем у переменной numbers вызываем метод .append(), передав в него распакованный список [4, 5].

В конце вызываем функцию print(), передав в неё переменную numbers для вывода результата.


Что могло пойти не так?
Функции в Python принимают два вида аргументов: позиционные и ключевые.
В нашем случае, мы передаём в метод .append() один позиционный аргумент - список [4, 5], однако, затем мы применяем к нему распаковку. Мы уже писали про работу распаковки в разборе задачи "Найди ошибку №2".

Всё дело в том, что, когда применяется распаковка, все элементы передаются как отдельные аргументы, в связи с чем и получаем ошибку TypeError, поскольку метод .append() принимает только один позиционный аргумент, а мы ему передаём два.
🔥6
Подготовили видео ко вчерашней задаче!

https://youtube.com/shorts/gx1UZlqQ3sc

Будем благодарны за лайк и комментарий!
🔥8