Выполнение функции перед выходом.
Как вызвать функцию перед выходом из программы в Python?
Для этого нужно использовать модуль atexit. Он регистрирует функции, которые выполняются перед завершением процесса интерпретатора.
🔸 Этот функционал работает и в обычном режиме без интерактивной консоли.
#tricks #libs
Как вызвать функцию перед выходом из программы в Python?
Для этого нужно использовать модуль atexit. Он регистрирует функции, которые выполняются перед завершением процесса интерпретатора.
import atexitТеперь попробуйте завершить процесс и увидите сообщение
def before_exit():
print('BEFORE EXIT')
atexit.register(before_exit)
>>> exit()🔸 Для регистрации такой функции в REPL пригодится startup скрипт.
BEFORE EXIT
🔸 Этот функционал работает и в обычном режиме без интерактивной консоли.
#tricks #libs
Стартап-скрипт это удобное место для изменения внешнего вида REPL. Например замена символов строки приглашения или добавление автокомплитов по TAB.
Давайте заменим символы строки приглашения. Для этого нужно поменять переменные sys.ps1 и sys.ps2. Символами может быть даже эмодзи.
Напишите это в стартап-скрипте:
___________
Еще пример python-startup скрипта с просторов гитхаба.
И пример от меня, рандомный смайл на каждой строке 😂
#tricks #libs
Давайте заменим символы строки приглашения. Для этого нужно поменять переменные sys.ps1 и sys.ps2. Символами может быть даже эмодзи.
Напишите это в стартап-скрипте:
import sys
sys.ps1 = '⏩ '
sys.ps2 = '⏳ '
А как насчет динамически изменяемой строки? Это тоже можно. Создаём класс, наследованный от строки и определяем что он возвращает при печати.import sys
class PS1(object):
def __init__(self):
self.s = True
def __str__(self):
self.s = not self.s
return '\033[97m█◣ \033[0m ' if self.s else '\033[34m█◤ \033[0m '
sys.ps1 = PS1()
sys.ps2 = '▼ '
Попробуйте поработать с этим)___________
Еще пример python-startup скрипта с просторов гитхаба.
И пример от меня, рандомный смайл на каждой строке 😂
#tricks #libs
Чем отличаются эти термины?
Шифрование
Кодирование
Хеширование
🔸 Шифрование
Обратимое преобразование информации с целью скрыть её содержимое. Шифруются данные с помощью секретного ключа, без которого расшифровать данные в исходное состояние невозможно.
Примеры использования:
- Шифрование бинарных файлов и архивов с помощью пароля
- Шифрование текста
🔸 Кодирование
Это преобразование данных из одного вида в другой. При этом содержимое данных остаётся прежним, меняется лишь форма (способ представления данных). Всегда можно вернуть данные в прежний вид с помощью обратного кодирования (декодирование).
Примеры использования:
- Кодирование текста из ASCII в UTF-8
- Кодирование изображения из BMP в TIF
- Кодирование строки в байты
🔸 Хеширование
Необратимое преобразование данных в строку определённой длины. Содержимое хеш-строки строго зависит от исходных данных и сильно изменяется даже если в данных изменить 1 бит. Хеширование всегда выдаёт одинаковый результат при одинаковых исходных данных. "Дехешировать" строку обратно в данные невозможно.
Примеры использования:
- Хранение пароля в базе данных в виде хеш-строки не раскрывает пароль и оставляет возможность проверять правильность введённого пользователем пароля.
- Хеш-строку файла еще называют контрольной суммой. Позволяет быстро проверить одинаковы ли файлы сравнив лишь хеши этих файлов. Даже если один пиксель в картинке изменится, контрольная сумма будет другой. Очень полезно для проверки необходимости обновления файлов по сети или поиска файлов.
🐍 Модули
🔹 Для работы с криптографией в Python используются внешние модули
cryptography
PyCrypto
🔹Хеширование и другие манипуляции с паролями и токенами
crypt
hashlib
secrets
hmac
Информация здесь
🔹 Всё что связано с кодировками
codecs
#libs
Шифрование
Кодирование
Хеширование
🔸 Шифрование
Обратимое преобразование информации с целью скрыть её содержимое. Шифруются данные с помощью секретного ключа, без которого расшифровать данные в исходное состояние невозможно.
Примеры использования:
- Шифрование бинарных файлов и архивов с помощью пароля
- Шифрование текста
🔸 Кодирование
Это преобразование данных из одного вида в другой. При этом содержимое данных остаётся прежним, меняется лишь форма (способ представления данных). Всегда можно вернуть данные в прежний вид с помощью обратного кодирования (декодирование).
Примеры использования:
- Кодирование текста из ASCII в UTF-8
- Кодирование изображения из BMP в TIF
- Кодирование строки в байты
🔸 Хеширование
Необратимое преобразование данных в строку определённой длины. Содержимое хеш-строки строго зависит от исходных данных и сильно изменяется даже если в данных изменить 1 бит. Хеширование всегда выдаёт одинаковый результат при одинаковых исходных данных. "Дехешировать" строку обратно в данные невозможно.
Примеры использования:
- Хранение пароля в базе данных в виде хеш-строки не раскрывает пароль и оставляет возможность проверять правильность введённого пользователем пароля.
- Хеш-строку файла еще называют контрольной суммой. Позволяет быстро проверить одинаковы ли файлы сравнив лишь хеши этих файлов. Даже если один пиксель в картинке изменится, контрольная сумма будет другой. Очень полезно для проверки необходимости обновления файлов по сети или поиска файлов.
🐍 Модули
🔹 Для работы с криптографией в Python используются внешние модули
cryptography
PyCrypto
🔹Хеширование и другие манипуляции с паролями и токенами
crypt
hashlib
secrets
hmac
Информация здесь
🔹 Всё что связано с кодировками
codecs
#libs
⭐️ На этой неделе преодалён рубеж в 1К подписчкивов!
Спасибо вам, что читаете мои заметки 😍.
Это хорошая мотивация к развитию. Давайте вместе определим вектор этого развития. Как вы думаете, чего больше всего сейчас не хватает этому каналу?
Спасибо вам, что читаете мои заметки 😍.
Это хорошая мотивация к развитию. Давайте вместе определим вектор этого развития. Как вы думаете, чего больше всего сейчас не хватает этому каналу?
Final Results
23%
💬 Чат для обсуждений и вопросов
20%
👍 Кнопки с реакциями под постом
55%
🎬 Видео уроки или видео курс
43%
📝 Блог с длинными статьями
12%
🎤 Стримы
Спасибо за ваши ответы. Думаю, результат опроса вполне очевиден.
Пойду обдумаю варианты реализации 😉
Пойду обдумаю варианты реализации 😉
В Python2 была интересная возможность кодировать строку с помощью ZIP-архивации.
Ведь что такое кодирование? Просто преобразование данных из одного вида в другой. Компрессия это тоже просто другая форма данных.
Представление данных в виде ZIP просто и легко сокращает размер этих данных. Это бывает полезно или даже критично при передаче данных по медленным каналам.
Пробуем преобразовать обратно.
Пытливые умы заметили, что мы нифига не сэкономили 😭
Да, это так. Но вся сила ZIP раскрывается на больших данных
Да, круто, но к чемуто это я? Дело в том что в Python3 этот код не сработает.
Во-первых, кодек переименован в "zlib_codec", во-вторых подобный код вызовет ошибку и отправит нас в модуль codecs.
И что теперь? Неужели я предлагаю заняться "некрокодингом" на Python2? Нет, не нужно тревожить пенсионера 🚑.
Всё будет ясно вследующем посте.
#libs
Ведь что такое кодирование? Просто преобразование данных из одного вида в другой. Компрессия это тоже просто другая форма данных.
Представление данных в виде ZIP просто и легко сокращает размер этих данных. Это бывает полезно или даже критично при передаче данных по медленным каналам.
# Python2Да, в результате это нереально прочитать, но мы же понимаем что это просто такая форма данных. Наша строка всё еще где-то там.
>>> my_str = 'Hello ZIP'
>>> my_zip_str = my_str.encode('zip')
>>> print my_zip_str
xЬєH═╔╔WИЄ♀ ☼╨♥️
Пробуем преобразовать обратно.
>>> my_zip_str.decode('zip')
'Hello ZIP'
Всё на месте!Пытливые умы заметили, что мы нифига не сэкономили 😭
>>> print len(my_str), len(my_zip_str)Увеличили размер почти в 2 раза!
9, 17
Да, это так. Но вся сила ZIP раскрывается на больших данных
>>> my_str = 'Hello ZIP ' * 100Чем больше строка и чем больше в ней повторов, тем лучше она сожмётся. В данном случае в 37 раз меньше данных.
>>> my_zip_str = my_str.encode('zip')
>>> print len(my_str), len(my_zip_str)
1000 27
Да, круто, но к чемуто это я? Дело в том что в Python3 этот код не сработает.
Во-первых, кодек переименован в "zlib_codec", во-вторых подобный код вызовет ошибку и отправит нас в модуль codecs.
my_str.encode('zlib_codec')
LookupError: 'zlib_codec' is not a text encoding; use codecs.encode() to handle arbitrary codecs
Данный функционал можно повторить и в Python3 но кода получится куда больше.И что теперь? Неужели я предлагаю заняться "некрокодингом" на Python2? Нет, не нужно тревожить пенсионера 🚑.
Всё будет ясно вследующем посте.
#libs
Вы знаете, что строки в Python можно кодировать и декодировать в разные кодировки.
А можно ли добавить свою кодировку в этот список?
Можно! И сейчас мы это сделаем. Давайте добавим ZIP-кодировку из Python2, о которой мы говорили в прошлом посте.
Для начала нам нужен алгоритм. Я хочу сжимать строку через ZIP и после получения байтов преобразовывать их в строку через base64 (можно и без base64). Получится такой код:
Обратный алгоритм декодирования
Теперь, чтобы создать кодек на базе этих алгоритмов, следует воспользоваться функций codecs.register().
В неё подаётся имя функции которая должна вернуть объект codecs.CodecInfo.
Данный объект будет содержать две функции - кодирование и декодирование. Это и будет наш кодек.
Давайте назовём наш кодек просто "z". Тогда его создание будет выглядеть как-то так:
Можно еще уменьшить размер если обойтись без BASE64. Но тогда вы получите чистые байты и как строку их передать уже не получится.
PS. А вот стандартный и самый короткой способ для ZIP-сжатия байтов в Python3
#tricks
>>> s = 'Привет'И другие...
>>> s.encode() # в байты
b'\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82'
>>> s.encode('ascii') # в ASCII (если получится)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
>>> s.encode('euc_jp') # японская кодировка
b'\xa7\xb1\xa7\xe2\xa7\xda\xa7\xd3\xa7\xd6\xa7\xe4'
>>> s.encode('hz') # Simplified Chinese
b"~{'1'b'Z'S'V'd~}"
А можно ли добавить свою кодировку в этот список?
Можно! И сейчас мы это сделаем. Давайте добавим ZIP-кодировку из Python2, о которой мы говорили в прошлом посте.
Для начала нам нужен алгоритм. Я хочу сжимать строку через ZIP и после получения байтов преобразовывать их в строку через base64 (можно и без base64). Получится такой код:
import zlib, base64Да, строка получилась длинней чем была. Но мы помним, что всё будет иначе если исходная строка большая.
>>> orig = 'hello python'
>>> compressed = zlib.compress(orig.encode(), 5)
>>> compresed_b = base64.encodebytes(compressed)
>>> print(compresed_b)
b'eF7LSM3JyVcoqCzJyM8DAB7wBNc='
Обратный алгоритм декодирования
>>> compressed = base64.decodebytes(compresed_b)Отлично! 😎
>>> restored = zlib.decompress(compressed).decode()
>>> orig == restored
True
Теперь, чтобы создать кодек на базе этих алгоритмов, следует воспользоваться функций codecs.register().
В неё подаётся имя функции которая должна вернуть объект codecs.CodecInfo.
Данный объект будет содержать две функции - кодирование и декодирование. Это и будет наш кодек.
Давайте назовём наш кодек просто "z". Тогда его создание будет выглядеть как-то так:
import zlib, base64, codecsТестим!
def z_encode(data):
return base64.encodebytes(zlib.compress(data.encode(), 5)), 0
def z_decode(data):
return zlib.decompress(base64.decodebytes(data)).decode(), 0
def z_search(encoding_name):
return codecs.CodecInfo(z_encode, z_decode, name='z')
codecs.register(z_search)
>>> s = 'Hello New codec!'Теперь обратно
>>> s_enc = s.encode('z')
>>> print(s_enc)
b'eF7zSM3JyVfwSy1XSM5PSU1WBAAvxwV+\n'
>>> s_enc.decode('z')
'Hello New codec!'
А теперь практика!. Сжимаем JSON со списком файлов >>> from pathlib import PathПрофит почти в 10 раз!
>>> import json
>>> files = list(map(str, list(Path('~/Documents').expanduser().glob('**/*'))))
>>> print(len(files))
5390
>>> text = json.dumps(files)
>>> print(len(text))
513839
>>> enc = text.encode('z')
>>> print(len(enc))
53317
Можно еще уменьшить размер если обойтись без BASE64. Но тогда вы получите чистые байты и как строку их передать уже не получится.
PS. А вот стандартный и самый короткой способ для ZIP-сжатия байтов в Python3
>>> import codecs(спасибо @amarovita за пример кода)
>>> codecs.encode(my_bytes, 'zip'))
#tricks
Те, кто в Python не первый день, хорошо знают, что на число можно умножить не только число, но и другие типы. Главное, чтобы у этих типов была реализация такой операции.
1. Если множитель справа, то вам нужно реализовать метод
Например, при умножении матриц имеет значение порядок операндов.
Для других операторов, таких как деление или сдвиг, очень важно кто с какой стороны находится.
# list
>>> [1] * 3
[1, 1, 1]
# tuple
>>> (2, 3) * 3
(2, 3, 2, 3, 2, 3)
# string
>>> "A" * 3
"AAA"
Так работает полиморфизм стандартных типов. Интересно здесь то, что это сработает и в том случае, когда порядок операндов обратный. То есть int умножить на [тип].# list
>>> 3 * [1]
[1, 1, 1]
# tuple
>>> 3 * (2, 3)
(2, 3, 2, 3, 2, 3)
# string
>>> 3 * "A"
"AAA"
Если хотите реализовать такое поведение в ваших классах то следует помнить два момента:1. Если множитель справа, то вам нужно реализовать метод
__mul__, наш класс это первый операнд, то есть слева.myType * 3
2. Если множитель слева, то вам нужно реализовать метод __rmul__, наш класс это второй операнд, справа.3 * myType
Всё тоже самое можно делать и для других математических операторов. И если в этом примере действие и результат будут фактически одинаковыми, то бывают ситуации, когда это не так. Например, при умножении матриц имеет значение порядок операндов.
Для других операторов, таких как деление или сдвиг, очень важно кто с какой стороны находится.
>>> 2/4, 4/2
(0.5, 2.0)
>>> 2<<3, 3<<2
(16, 12)
>>> 100%15, 15%100
(10, 15)
#tricks #basic💬 Теперь у канала есть группа для обсуждений!
Создание такой группы не было в приоритете для канала. Но это обязательное условие для возможности комментировать посты. Ведь комментарий это просто ответ на пост в группе.
Добавляю группу в качестве эксперимента и именно для комментариев. Если вдруг всё это превратится в неконтролируемый спам, то лучше удалить такое безобразие.
Отсюда правила, которые я прошу соблюдать:
🔸 Пишите только по делу. Флуд наказуем!
🔸 В чат писать только общие вопросы, не относящиеся к какому-либо посту. Остальное в комментарии.
🔸 Соблюдайте все стандартные правила общения и хорошего тона.
Давайте сделаем общение приятным 😉
➡️ Войти в группу
PS. Если внизу новых постов нет кнопки комментирования, то вам следует обновить Telegram.
Создание такой группы не было в приоритете для канала. Но это обязательное условие для возможности комментировать посты. Ведь комментарий это просто ответ на пост в группе.
Добавляю группу в качестве эксперимента и именно для комментариев. Если вдруг всё это превратится в неконтролируемый спам, то лучше удалить такое безобразие.
Отсюда правила, которые я прошу соблюдать:
🔸 Пишите только по делу. Флуд наказуем!
🔸 В чат писать только общие вопросы, не относящиеся к какому-либо посту. Остальное в комментарии.
🔸 Соблюдайте все стандартные правила общения и хорошего тона.
Давайте сделаем общение приятным 😉
➡️ Войти в группу
PS. Если внизу новых постов нет кнопки комментирования, то вам следует обновить Telegram.
Сегодня состоялся релиз Python 3.9! 🎉🥳🚀
Для тех кто пишет много кода очень важна краткость. Именно этот релиз добавляет нам удобную запись объединения словарей.
Вместо такой записи:
Остальные подробности на странице релиза:
https://www.python.org/downloads/release/python-390/
Для тех кто пишет много кода очень важна краткость. Именно этот релиз добавляет нам удобную запись объединения словарей.
Вместо такой записи:
d3 = {**d1, **d2}
теперь можно писать так:d3 = d1 | d2Конечно это не единственная новая фича.
Остальные подробности на странице релиза:
https://www.python.org/downloads/release/python-390/
Python.org
Python Release Python 3.9.0
The official home of the Python Programming Language
А вы ждёте Qt6 как жду его я? )))
Наверняка, те кто ждёт, уже в курсе, но я уточню даты релизов.
- Qt 6.0 Feature freeze - 31.8.2020
- Qt 6.0 Alpha - 2.10.2020
- Qt 6.0 Beta 1 - 15.10.2020
- Qt 6.0.0 RC - 17.11.2020
- Qt 6.0.0 Final - 1.12.2020
Полный список https://wiki.qt.io/Qt_6.0_Release
Между тем, библиотеки PySide3 ждать не стоит. Дело в том, что разработчики решили синхронизировать версии библиотек C++ и Qt for Python.
Так что ждём сразу PySide6!
#qt
Наверняка, те кто ждёт, уже в курсе, но я уточню даты релизов.
- Qt 6.0 Feature freeze - 31.8.2020
- Qt 6.0 Alpha - 2.10.2020
- Qt 6.0 Beta 1 - 15.10.2020
- Qt 6.0.0 RC - 17.11.2020
- Qt 6.0.0 Final - 1.12.2020
Полный список https://wiki.qt.io/Qt_6.0_Release
Между тем, библиотеки PySide3 ждать не стоит. Дело в том, что разработчики решили синхронизировать версии библиотек C++ и Qt for Python.
Так что ждём сразу PySide6!
#qt
🖨 Зачем подменять стандартную функцию print()?
В Python3 директива print() стала функцией, то есть объектом, с которым мы можем делать что угодно. Во 2-м Python мы такого лишены.
Как можно изменить стандартное поведение этой функции?
Обычно подменяют объект sys.stdout, что работает и во 2-м. Но будем действовать через builtins. При этом изменим только функцию print(), а stdout останется прежним.
Что нам потребуется сделать?
1. Создать функцию, которая заменит print и не сломает стандартное поведение
2. Подменить объект builtins.print
Давайте думать варианты.
🔸 Изменить аргументы по умолчанию.
Порой во время разработки приложения требуется именно распечатывать информацию в консоль через print(). Если это сервер, то всякий раз приходится дописывать
Приходилось пару раз рефакторить код сервера с очень запутанной структурой. На этапе избавления от принтов я не мог найти где распечатывается пустой список?! Ни одного принта по проекту нет а он распечатывается😢 Давайте заставим функцию print() сообщать нам где она находится.
Например добавлять что-то в начале, изменять цвет, заменять символьные смайлы на юникод и тд.
Вот пример от меня. В Python 3.8 добавили возможность через f-string распечатывать имя переменной вместе с её значением:
🌎 Полный код здесь
🔸 Отключить принт повсеместно!
Да, бывает и такое нужно). Кроме простого отключения (код сами догадайтесь какой) можно заменять всё на одинаковое сообщение, сделав принт бесполезным. Чтобы не использовали принт в проектах!
🔸 Заменить все принты на нормальное логирование.
Тоже вариант, но не особо полезный. Лучше писать нормальный логгинг чем так "костылять". Ну а для тренировки можно попробовать реализовать и этот вариант. Думаю, сами справитесь)
_________________________
Стоить ещё учесть пару моментов:
- эту подмену следует делать в самом начале работы приложения, в скрипте с которого начинается запуск. Удобно делать через стартап скрипт. Исходники при этом менять не требуется.
- функция изменится повсеместно во всех модулях на время сессии
- stdout не изменён, то есть обычный логгер будет писать в консоль нормально.
- Мы подменяем функцию на другую, а значит help(print) не покажет нам документацию,
- в моих примерах кое-где не обрабатывается kwargs. Не копируйте вслепую, всегда понимайте что делаете или не делайте вовсе.
Присылайте в коменты свои варианты! 😎
#tricks
В Python3 директива print() стала функцией, то есть объектом, с которым мы можем делать что угодно. Во 2-м Python мы такого лишены.
Как можно изменить стандартное поведение этой функции?
Обычно подменяют объект sys.stdout, что работает и во 2-м. Но будем действовать через builtins. При этом изменим только функцию print(), а stdout останется прежним.
Что нам потребуется сделать?
1. Создать функцию, которая заменит print и не сломает стандартное поведение
2. Подменить объект builtins.print
import builtins
_print = builtins.print
builtins.print = lambda *a, **kw: _print(*a, **kw)
В примере выше я заменил print но не добавил никакого функционала. Сейчас print() работает как и прежде, только через посредника.Давайте думать варианты.
🔸 Изменить аргументы по умолчанию.
Порой во время разработки приложения требуется именно распечатывать информацию в консоль через print(). Если это сервер, то всякий раз приходится дописывать
flush=True чтобы очищался буфер вывода и мы видели в консоли текст сразу же. Давайте сделаем так чтобы этот аргумент по умолчанию был True. Тогда лямбда будет выглядеть так:lambda *a, **kw: _print(*a, **{**kw, 'flush': True})
🔸 Поиск принтов в коде.Приходилось пару раз рефакторить код сервера с очень запутанной структурой. На этапе избавления от принтов я не мог найти где распечатывается пустой список?! Ни одного принта по проекту нет а он распечатывается😢 Давайте заставим функцию print() сообщать нам где она находится.
import builtins, sys
_print = builtins.print
def _located_print(*args, **kwargs):
_print(*args, **kwargs)
f = sys._getframe().f_back
_print('=> File:', f.f_code.co_filename,
'| line', f.f_lineno)
builtins.print = _located_print
Выйдет примерно так:>>> print('Hello')
Hello
=> File: /path/to/script.py | line: 1
🔸 Как-либо модифицировать все принты. Например добавлять что-то в начале, изменять цвет, заменять символьные смайлы на юникод и тд.
Вот пример от меня. В Python 3.8 добавили возможность через f-string распечатывать имя переменной вместе с её значением:
>>> value = 123
>>> print(f"{value=}")
value=123
Аналогичный функционал я повторил через подмену функции print(). 🌎 Полный код здесь
🔸 Отключить принт повсеместно!
Да, бывает и такое нужно). Кроме простого отключения (код сами догадайтесь какой) можно заменять всё на одинаковое сообщение, сделав принт бесполезным. Чтобы не использовали принт в проектах!
import builtins
_print = builtins.print
builtins.print = lambda *a, **kw: _print("Don't use prints!")
Получится что-то такое>>> print('Debug message')
Don't use prints!
Но это больше похоже на шутку, реализовать которую помогут стартап скрипты, о которых юзер не догадывается 😝🔸 Заменить все принты на нормальное логирование.
Тоже вариант, но не особо полезный. Лучше писать нормальный логгинг чем так "костылять". Ну а для тренировки можно попробовать реализовать и этот вариант. Думаю, сами справитесь)
_________________________
Стоить ещё учесть пару моментов:
- эту подмену следует делать в самом начале работы приложения, в скрипте с которого начинается запуск. Удобно делать через стартап скрипт. Исходники при этом менять не требуется.
- функция изменится повсеместно во всех модулях на время сессии
- stdout не изменён, то есть обычный логгер будет писать в консоль нормально.
- Мы подменяем функцию на другую, а значит help(print) не покажет нам документацию,
__name__ будет неверный и тд. Так что не забывайте использовать functools.wraps- в моих примерах кое-где не обрабатывается kwargs. Не копируйте вслепую, всегда понимайте что делаете или не делайте вовсе.
Присылайте в коменты свои варианты! 😎
#tricks
Gist
print_value_name.py
GitHub Gist: instantly share code, notes, and snippets.
В Python можно делать рекурсивные связи.
Например, список вложенный сам в себя:
#tricks
Например, список вложенный сам в себя:
>>> x = []Словари вложенные друг в друга:
>>> x.append(x)
>>> print(x)
[[...]]
>>> a = {}
>>> b = {}
>>> a['b'] = b
>>> b['a'] = a
>>> print(a)
{'b': {'a': {...}}}
Зачем это нужно? Лично я пока не сталкивался с подобными задачами, но, скорее всего, они есть)#tricks
🙄 Разминка для ума!
Треугольник Серпинского, интересная фигура которую построить достаточно просто.
Алгоритм такой:
1. создаём любые 3 точки на плоскости
2. из этих точек случайно выбираем любую, как начальную
3. случайно выбираем любую точку из этих же трёх точек как цель
4. перемещаемся в сторону цели на половину расстояния
5. повторяем бесконечно с пункта 3
Если сделать достаточно много итераций то вырисовывается интересная фигура. Треугольник, в который вписаны более мелкие треугольники. Это самый настоящий фрактал!
Я собрал пример построения такой фигуры на базе Qt.
🌎 Код можно посмотреть здесь.
С помощью paintEvent я рисую точки по озвученному алгоритму. Каждые 10 секунд либо по клику на виджете строится следующий треугольник.
Особенности примера:
🔸 Атрибут Qt.WA_OpaquePaintEvent позволяет сохранить то, что было нарисовано в прошлой итерации. Таким образом мы видим постепенное наполнение точек а не мелькающую одну точку.
🔸 QTimer позволяет создавать отложенные вызовы один раз или с повторением через интервал.
🔸 QColor.fromHsv() позволяет создать рандомный но предсказуемый цвет с помощью HSV схемы. Не слишком светлый и не слишком тёмный но всегда с разный. Рандомизации подвергается только смещение по цветовому кругу (Hue), яркость (Value) и насыщенность (Saturation) можно контролировать отдельно в своих пределах или оставить статичными. Обычный рандом цвета по RGB не даёт такой предсказуемый результат.
🔸 Каждый новый цикл с новым треугольником предварительно затемняет предыдущие через этот вызов
Если сделать виджет фулскрин, то у нас получится некий ScreenSaver)))
🔸 Да, я знаю, что рисование в Qt не самый лучший способ сделать этот пример) Скорее всего самый НЕподходящий. Попробуйте сделать тоже самое но другими средствами.
#qt #source #tricks
Треугольник Серпинского, интересная фигура которую построить достаточно просто.
Алгоритм такой:
1. создаём любые 3 точки на плоскости
2. из этих точек случайно выбираем любую, как начальную
3. случайно выбираем любую точку из этих же трёх точек как цель
4. перемещаемся в сторону цели на половину расстояния
5. повторяем бесконечно с пункта 3
Если сделать достаточно много итераций то вырисовывается интересная фигура. Треугольник, в который вписаны более мелкие треугольники. Это самый настоящий фрактал!
Я собрал пример построения такой фигуры на базе Qt.
🌎 Код можно посмотреть здесь.
С помощью paintEvent я рисую точки по озвученному алгоритму. Каждые 10 секунд либо по клику на виджете строится следующий треугольник.
Особенности примера:
🔸 Атрибут Qt.WA_OpaquePaintEvent позволяет сохранить то, что было нарисовано в прошлой итерации. Таким образом мы видим постепенное наполнение точек а не мелькающую одну точку.
🔸 QTimer позволяет создавать отложенные вызовы один раз или с повторением через интервал.
🔸 QColor.fromHsv() позволяет создать рандомный но предсказуемый цвет с помощью HSV схемы. Не слишком светлый и не слишком тёмный но всегда с разный. Рандомизации подвергается только смещение по цветовому кругу (Hue), яркость (Value) и насыщенность (Saturation) можно контролировать отдельно в своих пределах или оставить статичными. Обычный рандом цвета по RGB не даёт такой предсказуемый результат.
🔸 Каждый новый цикл с новым треугольником предварительно затемняет предыдущие через этот вызов
painter.fillRect(rec, QColor(0, 0, 0, 100))
То есть полупрозрачный цвет. Таким образом, чем старше треугольник, тем он темней. Если сделать виджет фулскрин, то у нас получится некий ScreenSaver)))
🔸 Да, я знаю, что рисование в Qt не самый лучший способ сделать этот пример) Скорее всего самый НЕподходящий. Попробуйте сделать тоже самое но другими средствами.
#qt #source #tricks
А давайте познакомимся с аудиторией канала поближе!
Для начала определим уровень владения Python и программированием в целом. Это поможет мне лучше выбирать контент!
Напиши, какой твой уровень в Python?
Для начала определим уровень владения Python и программированием в целом. Это поможет мне лучше выбирать контент!
Напиши, какой твой уровень в Python?
Final Results
45%
🐥 Базовый. Только начал изучать Python.
47%
🤪 Средний. Пишу уверенно, но нужно еще учиться.
6%
😎 Профи. Давно работаю профессионально.
1%
🤓 Ментор. Преподаю Python как эксперт.
Python Заметки pinned «А давайте познакомимся с аудиторией канала поближе!
Для начала определим уровень владения Python и программированием в целом. Это поможет мне лучше выбирать контент!
Напиши, какой твой уровень в Python?»
Для начала определим уровень владения Python и программированием в целом. Это поможет мне лучше выбирать контент!
Напиши, какой твой уровень в Python?»
Давайте немного прокачаем стандартный словарь. Зачем? А потому что Python это позволяет)))
Добавим возможность работать с ключами словаря как с атрибутами объекта. Для этого нам потребуется определить три метода:
Наследоваться будем от стандартного словаря
Но помните , если Python позволяет это делать, это не значит что это можно делать 👮♂️!
Подобные эксперименты лучше оставить для развлечения и не допускать в прод.
Хорошая разминка, не более того.
#tricks
Добавим возможность работать с ключами словаря как с атрибутами объекта. Для этого нам потребуется определить три метода:
__getattr__ - получение атрибута__setattr__ - изменение атрибута__delattr__ - удаление атрибутаНаследоваться будем от стандартного словаря
class _AttribDict(dict):Подменяем стандартный словарь в одну строку
def __getattr__(self, name):
return self[name]
def __setattr__(self, name, value):
self[name] = value
def __delattr__(self, name):
del self[name]
__import__('builtins').__dict__['dict'] = _AttribDict
Всё, можно тестить 😬>>> obj = dict(name='Object1', id=14)Выглядит как обычный словарь
>>> print(obj)
{'name': 'Object1', 'id': 14}
>>> obj['name'] = 'Thing 1'Изменение ключей работает. То есть стандартное поведение не сломали. А теперь попробуем обратиться к атрибутам
>>> print(obj['name'])
Thing 1
>>> print(obj.name)Пробуем изменить ключ через атрибут
Thing 1
>>> obj.name = 'Thing 2'И удаляем ключ через атрибут
>>> print(obj.name)
Thing 2
del obj.nameТеперь с ключами словаря можно работать и обычным способом:
print(obj)
{'id': 14}
dict['key']и как с атрибутами:
dict.keyВыглядит интересно.
Но помните , если Python позволяет это делать, это не значит что это можно делать 👮♂️!
Подобные эксперименты лучше оставить для развлечения и не допускать в прод.
Хорошая разминка, не более того.
#tricks
А знаете ли вы, что в Bash есть особая переменная "$_" ? Из описания можно узнать, что в переменную "$_" помещается последний аргумент последней команды.
Что-то знакомое? Конечно, в Python есть примерно тоже самое.
Мы знаем, что дата первого релиза Bash (8 июня 1989) несколько раньше чем первый релиз Python (20 февраля 1991). Если учесть, что по задумке автора Python это агрегация самых успешных практик отовсюду, можно ли сказать что именно эта фишка к нему пришла из Bash? Ни подтверждения ни опровержения я пока не нашел.
Давайте просто считать это совпадением 😉
А как это может быть полезно в Bash?
Приведу простой пример, который оценят те, кто часто работает в терминале.
Допустим, нам надо создать директорию и зайти в неё. Что обычно делаем?
PS.
Символы "&&"" разделяют команды и означают, что требуется выполнить вторую команду только если первая завершилась успешно.
#linux #tricks
Что-то знакомое? Конечно, в Python есть примерно тоже самое.
Мы знаем, что дата первого релиза Bash (8 июня 1989) несколько раньше чем первый релиз Python (20 февраля 1991). Если учесть, что по задумке автора Python это агрегация самых успешных практик отовсюду, можно ли сказать что именно эта фишка к нему пришла из Bash? Ни подтверждения ни опровержения я пока не нашел.
Давайте просто считать это совпадением 😉
А как это может быть полезно в Bash?
Приведу простой пример, который оценят те, кто часто работает в терминале.
Допустим, нам надо создать директорию и зайти в неё. Что обычно делаем?
:~$ mkdir foldernameКак это сделать в одну команду?
:~$ cd foldername
:~/foldername$
:~$ mkdir foldername && cd foldernameУже лучше, но хочется короче, без повторов. Вот тут и пригодится наша переменная. Напомню, что в неё сохраняется последний аргумент предыдущей команды.
:~/foldername$
:~$ mkdir foldername && cd $__________________
:~/foldername$
PS.
Символы "&&"" разделяют команды и означают, что требуется выполнить вторую команду только если первая завершилась успешно.
#linux #tricks
Продолжаем знакомиться.
В какой сфере вы работаете или хотите работать?
В какой сфере вы работаете или хотите работать?
Final Results
22%
🖥 Десктоп приложения
19%
📱 Мобильные приложения
48%
🌍 Web-приложения
27%
💥 Компьютерная графика
18%
📈 Аналитика
29%
🤖 Машинное обучение
15%
🤔 Что-то другое