Python Заметки
2.31K subscribers
59 photos
2 videos
2 files
211 links
Интересные заметки и обучающие материалы по Python

Контакт: @paulwinex

⚠️ Рекламу на канале не делаю!⚠️

Хештеги для поиска:
#tricks
#libs
#pep
#basic
#regex
#qt
#django
#2to3
#source
#offtop
Download Telegram
Python по умолчанию кеширует числа int в диапазоне -5...256.
Думаю, это всем известный факт.

>>> a = 10
>>> b = 10
>>> a is b
True

>>> a = 270
>>> b = 270
>>> a is b
False

Но вот что интересно, это не сработает внутри модуля.

# matchtest.py ####
a = 270
b = 270
print(a is b)
# end file ########


>>> import matchtest
True

Почему одно и тоже работает по разному? Что за двойные стандарты?
Вот вам подсказка, в интерактивной консоли это можно повторить, запустив обе команды как одну.

>>> a = 270; b = 270
>>> a is b
True

А разница в том как интерпретатор получает код, точней какими порциями. Каждую "порцию" он "интерпретирует", попутно оптимизируя логику кода.
А оптимизация замечает нашу "бездарную писанину" и исправляет явные ошибки. Грубо говоря, такой код:

a = 270
b = 270

Превращается в нечто такое:

a = b = 270

Зачем создавать два одинаковых объекта когда можно создать один объект и две ссылки?

Если выполнять команды по отдельности то оптимизация не сработает, так как это отдельные объекты кода.
Если же это одна команда, введёная в консоль или код загружен из модуля, то интерпретатор увидит это как единый блок. Этап оптимизации изменит исходный код и это сведёт на нет наши исследования, выдав не то что мы ожидаем.

#triks
Помните трик с заменой строки в консоли с помощью символа "\r"? Рассказывал в этом посте.
Что будет если сделать несоклько таких символов? Мы вернёмся на несколько строк выше? Нет, так не сработает.
Как же сделать замену нескольких строк?

Для этого нужна хитрая комбинация символов:

\x1b[1A\x1b[2K

Что это вообще за магия? Это специальный код для управления курсором консоли.

\x1b : экранирующий символ означающий что дальше следует специальный символ. Он же символ ESC

[1A : команда "поднять курсор вверх". Есть и другие команды для перемещения курсора в разные стороны.

[2K : удалить текущую строку. "2" означает всю строку. Еще есть опции: "0" - от курсора до конца, "1" - от курсора к началу.

Итого, наша абракадабра значит - подняться на строку вверх и удалть всю строку.

Полный список специальных символов можно найти на этой странице.
Эти функции консоли широко используются. Например модуль colorama использует модификации для изменения цвета текста в консоли.

В демке на видео показана манипуляция тремя строками в консоли. Пишем три строки, удаляем три строки, и тд.

➡️ Код с демонстрацией

#triks
🔥12
В Linux стандартными средствами можно использовать часть оперативной памяти как диск. Для этого требуется указать тип монтирования tmpfs в команде mount

mount -t tmpfs -o size=5G tmpfs /mnt/ram

Теперь путь /mnt/ram можно использовать как обычный каталог. Для чего это может быть нужно?

▫️ Скорость работы с таким каталогом выше чем многие SSD и тем более HDD.
▫️ Если у вас очень быстрый SSD на NVMe M.2 то такой способ особо не прибавит вам скорости, но поможет сохранить ресурс SSD когда требуется обрабатывать очень много мелких файлов и оперативка позволяет выделить нужный объем.
▫️ Оперативка это энергозависимая память, поэтому выключении питания все файлы безвозвратно теряются. Такой "non persistent" каталог гарантирует удаление временных файлов.

Я написал небольшой скрипт для условного теста и сравнения скорости копирования файлов между SSD и RAM.
Вот мои результаты:

Single File Size: 30.0Gb

ssd > ssd: 0:00:12.850 / 2.3Gb/s
sdd > ram: 0:00:06.453 / 4.6Gb/s
ram > ram: 0:00:06.995 / 4.3Gb/s
ram > sdd: 0:00:06.217 / 4.8Gb/s

Dir size: 32.7Gb, File count: 11127

ssd > ssd: 0:00:15.063 / 2.2Gb/s
sdd > ram: 0:00:08.486 / 3.9Gb/s
ram > ram: 0:00:08.032 / 4.1Gb/s
ram > sdd: 0:00:07.026 / 4.7Gb/s

Скрипт для теста ↗️

На моём железе прирост скорости ~2x. Плюс экономия ресурса SSD.

В Windows такой фишки по умолчанию нет, но обязательно найдутся аналогичные решения

#linux #triks
👍9🔥21
Где можно применять моржовый (walrus) оператор? (Py3.8+)

Очевидное назначение моржового оператора - сократить количество кода. Сделать присвоение значения переменной и его использование в одно действие. Чаще всего используется в конструкциях if и while

if match := pattern.search(data):
print(match.groups())

while chunk := file.read(1024):
process(chunk)


Можно ли использовать его внутри f-string?

print(f'{x:=10}')
# NameError: name 'x' is not defined


Это синтаксис форматирования а не walrus. Чтобы превратить выражение в walrus используем скобки

print(f'{(x:=15)}')
# '15'
print(x)
# 15


Получается, что скобки помогут использовать walrus не только с if, while, match и тд.

Пример не самого очевидного присвоения значений переменным

x = (y := 1, 2)
print(x)
print(y)
# (1, 2)
# 1


Вызов функции тоже может быть использован как скобки для walrus

def get(): return 2
def do_it(x, y): return x + y

x = do_it(y := get(), y+3)
print(x, y)
# 7 2


Два "моржа" на одном пляже в одной строке

def compute(x): return x*2
def get_value(): return 1

if z := compute(x := get_value()):
print(f"compute({x}) = {z}")
else:
print(f"{x} is not valid value")
# compute(1) = 2


В следующем примере мы экономим не только код но и количество расчётов

list1 = [1, 2, 3, 4, 5]
# без walrus
list2 = [x*2 for x in list1 if x*2 % 15 == 0]
# c walrus
list2 = [(n := x*2) for x in list1 if n % 15 == 0]


Создание списка выполняется последовательно, поэтому можно объявить переменную в первом элементе и использовать в остальных

f = lambda v: v*2
[y := f(1), y**2, y**3]
# [2, 4, 8]


Более страшный пример с созданием lambda через walrus

[y := (f := lambda x, i: x*i)(3, 10), z:=f(y, 20), f(z, 30)]
# [30, 600, 18000]

не делайте так

Экономим один вызов lower() в простом выражении

is_palindrome = (w := word.lower()) == w[::-1]


И ещё пример экономии места в файле и времени CPU

try:
10 / 0
except Exception as err:
logger.log(message := f"Error, {err}!")
send_report(message)


А еще не будет ошибкой синтаксиса если использовать walrus перед return.

def calculate(a, b):
return result := a * b


Но, по очевидным причинам, смысла в этом нет 😄

#triks
👍16🤯31