Cool and Fun Python
540 subscribers
30 photos
8 videos
1 file
33 links
Крутой и весёлый Python. Случаи из практики и не только.
Download Telegram
Мультимножество. Часть 1, теоретическая

Для начала немного теории о множествах не только в Python, но и в математике в целом.

Множество - это набор уникальных элементов, которые могут быть любого типа (числа, буквы, предметы и т.д.). В множестве каждый элемент может встречаться только один раз.

Пример множества: 1, 2, 3, 4, 5. В этом множестве каждое число встречается только один раз. А если вы посмотрите вокруг себя и перечислите окружающие предметы (без повторов), то тоже получите множество: компьютер, телефон, кресло, стол.

Мультимножество - это набор элементов, где элементы могут повторяться. То есть в мультимножестве одинаковые элементы могут встречаться несколько раз.

Пример мультимножества: 1, 2, 2, 3, 3, 3. В этом мультимножестве число 2 встречается два раза, а число 3 - три раза.

👍 - отличное начало, продолжай
🥱 - долой теорию, давай код
👍23🥱2
Всем привет 👋

Увидел в одном канале вот такой код на картинке И немного загрустил. Ведь в нём куча повторяющихся блоков кода

Познавательная минутка 🤓
Принцип DRY (don't repeat yourself) рекомендует программистам не писать повторяющиеся строчки кода. И современные высокоуровневые языки программирования легко с этим справляются. Можно использовать функции и методы классов. А иногда достаточно обычного цикла.

Немного магии и картинка превращается в улучшению версию кода, в лучших традициях DRY
import time


def happy_birthday(name):
name = name.capitalize()
data = [("Happy Birthday to you.", 2, 1),
(f"Happy Birthday to {name}!", 1, 1),
("Happy Birthday to you.", 1, 1),
("Hip Hip Hooray!", 3, 0)]

for text, count, delay in data:
for step in range(count):
print(text)
time.sleep(delay)


happy_birthday("Python")

Кстати, с днём рождения языка. Python исполнилось 0b100001 годиков 🎂🍾🎉
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉8🍾3❤‍🔥1
Мультимножество. Часть 2, хардкодинг
👉начало👈

Для создания мультимножества в Python не нужно изобретать ни велосипед, ни варп двигатель. Достаточно взять словарь dict 🤓
Ключ словаря - элемент мультимножества.
Значение словаря - целое число, которое подсчитывает сколько раз элемент встречается в мультимножестве

# обычный список предметов в комнате
room = ['компьютер', 'телефон', 'кресло', 'стол', 'кресло', 'телефон', 'светильник']

# немного магии и получаем словарь как мультиможество
multiset = {}
for item in room:
if item in multiset:
multiset[item] += 1
else:
multiset[item] = 1

print(multiset)

Отлично! Теперь мы легко можем узнать сколько телефонов в комнате
print(multiset['телефон'])

И это всё, что нужно для создания и работы с мультимножествами?
Неа. Надо немного больше. Строчек 450(!) Python кода. Вот такого: https://telegra.ph/Multimnozhestvo-02-20
Что это за код расскажу в финальной части трилогии 😉
👍3👏2🤯1
This media is not supported in your browser
VIEW IN TELEGRAM
Мультимножество. Часть 3, финал
👉часть 1, теория👈
👉часть 2, хардкодинг👈

Что имеем "из коробки"?
1). В Python есть модуль collections.
2). В модуле написано ≈450 строк кода для создания класса Counter.
3). Counter расширяет возможности словаря dict, превращая его в мультимножество.

Как результат работы с готовым объектом Counter:
- возможность подсчитывать объекты итеририуемых последовательностей;
- складывать и вычитать мультимножества;
- проводить логические операции AND и OR с мультимножествами
- получать наиболее частые элементы мультимножества и многое др.

✍️ - беру на вооружение
🤯 - как это работает?

Ссылка с подробностями про мультимножество Counter
4🤯4👍2
Всех причастных к дню Защитника Отечества поздравляю с прошедшими праздником 🫡

И ловите несколько примеров использования мультимножества Counter.

0). Подсчет количества вхождений элементов в списке:
from collections import Counter

lst = [1, 2, 3, 1, 2, 3, 4, 5, 1, 2, 3]
counter = Counter(lst)

print(counter)
Кстати, вместо чисел могут быть любые объекты. Counter посчитает и bool'ы и классы.

1). Подсчет количества слов в тексте:
from collections import Counter

text = "Обычный текст. Обычно пословно разбиваем текст. Обычный подсчёт слов в тексте."
words = text.split()
counter = Counter(words)

print(counter)
Обратите внимание, что такой подход реагирует на знак препинания.

2). Подсчет количества символов в строке:
from collections import Counter

string = "abracadabra"
counter = Counter(string)

print(counter)

Лирическое отступление 😃
Когда-то давно вёл мероприятие онлайн. И показывал пример со словом «abracadabra». Стоило произнести его вслух, как платформа давала сбой, трансляция прерывалась. После трёх абракадабр решили вместе с участниками мероприятия заменить слово

3). На финал оставил пример посложнее. 10 самых используемых слов в тексте. Например в Войне и мир Л.Н. Толстого.
import re
from collections import Counter

def top_10_words(filename):
words_count = Counter()

with open(filename, 'r', encoding='utf-8') as file:
for line in file:
words = re.findall(r'\b\w+\b', line.lower())
words_count.update(words)

top_10 = words_count.most_common(10)
return top_10

filename = 'Война и мир.txt'
top_words = top_10_words(filename)
for word, count in top_words:
print(f'Слово "{word}" встретилось {count} раз')

Кстати, заметили как хитро закручен переход от мультимножества к регулярным выражениям? 🪄 Следующие несколько постов буду про них

✍️ - беру на вооружение
🤯 - как это работает?
🎉 - выходные для отдыха, а не кода
Please open Telegram to view this post
VIEW IN TELEGRAM
9🤯3🎉1
Немного философских мыслей мемов или просто делюсь наболевшим
🤣3👍2🔥1
Давным давно, в прошлом тысячелетии...
Регулярные выражения. Эпизод 4. Теоретический

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

По сути регулярные выражения являются отдельным языком. Они появились более пол сотни лет назад. Потом набрали популярность как часть языка программирования Perl. И лишь спустя годы перекочевали в уйму других ЯП.

В Python работа с регулярными выражениями осуществляется с помощью модуля re:
import re

Модуль предоставляет функции и методы для работы с регулярными выражениями, такие как re.search(), re.match(), re.findall() и кучу других.
Но если максимально упростить, модуль делает две вещи:

1). Позволяет создавать шаблоны. Обычные сырые строки с языком регулярных выражений внутри.

Познавательная минутка 🤓
Сырые строки (так же известные как raw string) в Python записываются как обычная строка, в одинарных или двойных кавычках. Но перед открывающей кавычкой ставится буквы r, сокращение от raw. Например сырая строка ниже может использоваться как шаблон для регулярного выражения из примера 3:
r'\b\w+\b'

2). Выбирать из большого текста маленький текст по шаблону.

Всё остальное - крутые навороты, упрощающие жизнь в поисках текста 🧠
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🤯21
This media is not supported in your browser
VIEW IN TELEGRAM
Всех причастных к международному женскому дню поздравляю с прошедшими праздником 💐

А вот и поздравление с регулярками подоспело:
import re

def congratulate(name):
pattern = r'(?i)\b(женщин\w*|девушк\w*|леди|дам\w*)\b'
if re.search(pattern, name):
return f"С Международным женским днем, {name}!"
else:
return f"С Международным женским днем!"

Обратите внимание на шаблон:
- для поиска без учёта регистра используется (?i);
- чтобы слово было словом, а не частью большого слова, используем \b до и после;
- для учёта любого окончания применяем \w* - любая буква ноль и более раз;
- вертикальная черта | работает как or. Достаточно одного из четырёх совпадений.

Если запустить, получим ожидаемый результат с упоминанием женщин или просто с поздравлением:
>>> congratulate("Дорогие женщины"))
'С Международным женским днем, Дорогие женщины!'
>>> congratulate("Уважаемые господа"))
'С Международным женским днем!'

P.S. Данный шаблон не даёт 100% гарантии 😉
>>> congratulate("Жан-Клод Ван Дамм")
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🔥1😁1
This media is not supported in your browser
VIEW IN TELEGRAM
Регулярные выражения

Выражение ?P<name> (ага, именно так, с большой P и треугольными скобками) используется для именования групп в регулярных выражениях, что делает код более читаемым и понятным.

Ловите простой пример использования ?P<name>:
import re

text = "Имя: Алексей, Возраст: 32, Город: Москва"

pattern = re.compile(r"Имя: (?P<name>\w+), Возраст: (?P<age>\d+), Город: (?P<city>\w+)")

match = pattern.match(text)
if match:
print("Имя:", match.group('name'))
print("Возраст:", match.group('age'))
print("Город:", match.group('city'))

В этом примере мы используем регулярное выражение с именованными группами для извлечения имени, возраста и города из текста. Функция match.group('name') позволяет получить значение, соответствующее группе с именем 'name'.

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


Открытие номер 1, .groupdict()

Метод groupdict() используется для получения словаря, содержащего именованные группы из последнего успешного совпадения регулярного выражения. Он полезен, когда есть много именованных групп в регулярном выражении и вы хотите получить все значения в виде словаря.

Ловите пример с groupdict():
import re

text = "Имя: Алексей, Возраст: 30, Город: Москва"

pattern = re.compile(r"Имя: (?P<name>\w+), Возраст: (?P<age>\d+), Город: (?P<city>\w+)")

match = pattern.match(text)
if match:
group_dict = match.groupdict()
print(group_dict)

Результатом будет словарь group_dict, где ключами будут имена групп из шаблона pattern, а значениями - соответствующие значения из текста text.

Телеграм ограничивает размер сообщения. Поэтому про открытие номер два, расскажу в следующем посте 😉

✍️ - беру на вооружение
🤯 - как это работает?
🎉 - выходные для отдыха, а не кода
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍3🤯3🎉3
Регулярные выражения. Открытие номер 2

Начало тут

Когда впервые познакомился с шаблоном ?P<name> в регулярках, прочитал в сети старую переписку Гвидо с...

Ага! С кем-то. Лично я запомнил его как Ларри Уолла, автора языка Perl. Но сейчас, при написании поста не смог найти ту самую древнюю переписку.
Если поделитесь ссылкой в комментариях, респект и уважуха. А пока будем считать это байкой старого айтишника. Садитесь поудобнее 😉


Когда Гвидо добавлял в язык Python регулярные выражения, он конечно же взял их из языка Perl. Почему?

Познавательная минутка 🤓
Perl был создан в 1987 году лингвистом Ларри Уоллом. И изначальная идея - язык для работы с текстом. А куда же тексту без регулярных выражений. Всё логично 🤓

Так вот, Гвидо захотел улучшить регулярки в Python. Он написал Ларри письмо, поинтересовался можно ли занять сочетание символов ?P (вопрос, заглавная P)? И Ларри сказал, что никаких планов на связку ?P у него нет.
После официально разрешения Гвидо использовал связку для расширения регулярок, добавил ?P<name>. Теперь он мог обращаться к найденным группам по имени. А заодно и складывать полученные группы в словарь по ключам.

Эта идея так понравилась, Ларри, что уже из Python перекочевала в Perl, а потом и в регулярные выражения как таковые.

Кстати, заглавная P в регулярке означает Python. Гвидо застолбил букву для своего языка. Вдруг регулярное выражение не прижилось бы.
Как показывает история, ?P<name> очень прижилось. И оно шикарно облегчает жизнь превращая объемный текст в словарь нужных данных.

Спасибо, Гвидо 🖖
👍6🔥2👨‍💻1
Несколько раз натыкался на вопросы и статьи про запуска кода по расписанию.

Хочет человек запускать свою функцию в 9:30 и 20:45. А ещё он пишет на Python. И начинаются варианты с time.sleep, с asyncio.sleep. Варианты с отдельными потоками или процессами. Кто-то использует сторонние модули, например schedule. Молодцы, ребята, чего уж. Много кодят ради запусков по расписанию 👍

Познавательная минутка 🤓
Запуск программ по расписанию использовался на компьютерах полсотни лет назад. Уже в 1970-х годах была программа (демон) для запуска других программ по расписанию. Вы когда-то слышали про cron? Это он претерпев несколько изменений запускает код по расписанию более 50 лет

Как вы догадались, для запуска когда по расписанию не нужно изобретать сложные Python костыли и велосипеды. Вводим в терминале crontab -e и добавим пару строк в конец файла:
30 9 * * * python /path/to/project.py
45 20 * * * python /path/to/project.py


Ура! Python файл project будет автоматически запущен дважды в сутки, в 9:30 (строка 1) и в 20:45 (строка 2) 😉

Заметили пустую строку после примера в cron? Как и Python фалы, файл crontab должен заканчиваться пустой строкой. Но в отличии от доброго Python, cron не прощает ошибки. Если пустой строки нет, cron проигнорирует последнюю. Ту, где запуск в 20:45.

P.S. Может ситуацию с последней пустой строкой и пофиксили. Но я за пару десятилетий привык её добавлять. Кому интересно, проверяйте, пишите результат в комментариях ✍️

#bash #crontab
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥31
И снова делюсь наболевшим. Улыбок вам и быстрых правок багов 💪😉

P.S. Пруфы из официальной документации

#юмор
😁51👍1
Гвидо ван Россум, создатель языка программирования Python, объявил о разработке собственной операционной системы. Отличительной особенностью новой ОС станет уникальная функция под названием GAL — Global Application Lock, позволяющая запускать за раз только одну программу.

«Мы стремимся к простоте и максимальной эффективности», — заявил ван Россум. «Без необходимости переключаться между задачами пользователи смогут полностью сосредоточиться на одной задаче, избежав отвлекающих факторов».

По словам разработчика, ОС будет идеальной для писателей, кодеров и всех, кто хочет уйти от многозадачности.

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

#юмор #неновости @notnewsgpt
😁4👍2🔥1
This media is not supported in the widget
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Про многозадачность

Недавно возникла задача параллельно выполнять три задачи. Ага, такая вот тавтология. 😀 Конечно же потоки сразу были отметены.

- Почему не потоки? - спросите вы.

Потому что с GIL потоки всегда последовательны.
Да, быстро переключаются.
Да, если нет сложных расчётов, ведут себя как параллельные задачи.
При детальном рассмотрении работают последовательно в рамках одного процесса на одном ядре одного процессора.
Не забывайте эту элементарную особенность классического Python.

Познавательная минутка 🤓
Для запуска трёх задач в виде процессов использовал модуль subprocess
import subprocess
from sys import executable
from os import getcwd

...
python_executable = executable subprocess.Popen([python_executable, 'project_dir/main.py'], cwd=getcwd())
...


✍️ - беру на вооружение
🤯 - как это работает?

#многопоточность
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯87👍1
Коротко об интересном

Недавно столкнулся с задачей выдернуть время из строки текста на русском языке.
Между созданием своего решения с нуля и поиском готового остановился на втором.
Представляю вашему вниманию rutimeparser.

Если коротко, то:
from rutimeparser import parse

text = "Завтра в 10:10"
date_time = parse(text, tz='Europe/Moscow')

✍️ - беру на вооружение
🤯 - как это работает?

#познавательно
4🤯4
Немного воспоминаний от автора канала

В далёком 2007 году я начал интересоваться Linux, особенно Gentoo. За пару дней скомпилировал ядро, модули, X11 и KDE. Всё с флагом -O3. Это означает, что операционная система адаптировалась под мой компьютер и стала быстрее и красивее, чем Windows XP. 🧓

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

Сейчас называю таких людей «юными и любознательными». Приятно изучать новое и радоваться своему прогрессу.

Через несколько лет перешёл на CLD (Calculate Linux Desktop), который основан на Gentoo с KDE. Всё необходимое было собрано и скомпилировано за меня. Не только операционная система, но и сотни программ для работы с текстом, изображениями, видео и многим другим устанавливаются с нуля за 20 минут.

С опытом я перешёл к стабильности. Нет смысла устанавливать бета-версии программ, если есть стабильные, но на 1-2 версии ниже. И если сервис был создан 5 лет назад и успешно выполняет свои задачи, не стоит обновлять его.

Работает - не лезь. 🤓

👨‍💻 - юный и любознательный
🎅 - работает - не лезу
#истории
Please open Telegram to view this post
VIEW IN TELEGRAM
🎅7👍6👨‍💻3
Новое — это хорошо забытое старое.

ast.literal_eval

👍 - спасибо, что напомнил
✍️ - записал, иду изучать
🤯 - жду подробности в следующем посту

#познавательно
🤯13👍31
Целую неделю ждал хотя бы 10 реакций 🤯. Не дождался. Этот пост посвящается девятку интересующихся. 🫡

Что же такое ast.literal_eval ? Если просто и коротко, то это функция для превращения строки str в другой питоновский тип данных.
Смотрите пример, чтобы всё понять:
import ast

# Возвращает None
result = ast.literal_eval('None')
print(result) # None
print(type(result)) # <class 'NoneType'>

# Возвращает список
result = ast.literal_eval('[1, 2, 3]')
print(result) # [1, 2, 3]
print(type(result)) # <class 'list'>

# Возвращает словарь
result = ast.literal_eval('{"key": "value"}')
print(result) # {'key': 'value'}
print(type(result)) # <class 'dict'>


Как видно из примера, функция literal_evel сама подбирает нужный тип для конвертации содержимого строки. Круто!

Внимание!
literal_eval удобно использовать, даже если вы не уверены в данных. Выполнить rm -rf / функция не сможет. Но будьте готовы отлавливать ошибки, если данные не поддаются преобразованию:
result = ast.literal_eval('a = 42')  # SyntaxError: invalid syntax
result = ast.literal_eval('Hi') # ValueError: malformed node or string on line 1: <ast.Name object at 0x7969dde980>


Для самых любопытных, напомню. 🤓
В Python есть модуль pickle. Он умеет мариновать питоновские типы в виде байт-файла. О нём писал тут и тут.

А ещё в Python есть модуль json. Он тоже умеет превращать строк в данные и наоборот. Про него я тут не писал. 🙃
#познавательно #lifehack
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍163🔥21🤔1
Столько реакций! Класс! Благодарю всех. 🥰

Сегодня день учителя. Надеюсь этот канал учит вас, даёт новые знания. А ваши вопросы в комментариях зачастую учат админа, заставляют освежить знания, изучить что-то новое.

Все мы учителя и ученики одновременно. Всех нас с праздником, с днём учителя! 👨‍🏫
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉13👍5👏2🤓1🤗1
Держите капельку знаний для работы с временем в Python. Речь пойдёт о timedelta - разнице между двумя точками во времени.
Решим простую задачу, сколько секунд прошло между двумя датами. Для простоты возьмём сегодняшнее число и время с интервалом в один час.

Вначале у нас всё хорошо.
from datetime import datetime

dt_gt = datetime(2024, 10, 10, 11, 11)
dt_lt = datetime(2024, 10, 10, 10, 11)
td = dt_gt - dt_lt
print(f'<{dt_gt}> - <{dt_lt}> = <{td}>')
print(f'{td.seconds = }')

# Результат
# <2024-10-10 11:11:00> - <2024-10-10 10:11:00> = <1:00:00>
# td.seconds = 3600


Из большего значения (более поздней даты) вычитаем меньшее значение. И получаем ожидаемую разницу в один час - 1:00:00.
У timedelta есть удобное свойство, seconds. Оно вернуло 3600 секунд.

Познавательная минутка 🤓
В одном часе 60 минут.
В одной минуте 60 секунд.
Следовательно в одном часе 60 × 60 = 3600 секунд.
А ещё в сутках 24 часа или 86400 секунд. Эти знания нам пригодятся после второго примера.

А теперь поменяем местами даты.
from datetime import datetime

dt_gt = datetime(2024, 10, 10, 11, 11)
dt_lt = datetime(2024, 10, 10, 10, 11)
td = dt_lt - dt_gt
print(f'<{dt_lt}> - <{dt_gt}> = <{td}>')
print(f'{td.seconds = }')

# Результат
# <2024-10-10 10:11:00> - <2024-10-10 11:11:00> = <-1 day, 23:00:00>
# td.seconds = 82800


Ранее мы убедились, что между датами 1 час или 3600 секунд. Но timedelta сообщает о разнице в 82800 секунд. 😨
Если присмотреться, timedelta теперь минус один день и плюс 23 часа.
Считаем -1 день = -24 часа.
-24 + 23 = -1 час или -3600 секунд.
Получается, что разница во времени посчитана верно. Но ожидаемы -3600 секунд мы не получили.

Что делать? 🤔 Смотреть пример 3.
from datetime import datetime

dt_gt = datetime(2024, 10, 10, 11, 11)
dt_lt = datetime(2024, 10, 10, 10, 11)
td = dt_lt - dt_gt
print(f'<{dt_lt}> - <{dt_gt}> = <{td}>')
print(f'{td.total_seconds() = }')

# Результат
# <2024-10-10 10:11:00> - <2024-10-10 11:11:00> = <-1 day, 23:00:00>
# td.total_seconds() = -3600.0


У объекта timedelta есть метод total_second. Он и вернул ожидаемые -3600 секунд. 🥳

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

Всем отличного времени, какая бы разница у него не была.

✍️ - беру на вооружение
🤯 - как это работает?

#познавательно #python
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍4🤯1