Dmatryusофрения
41 subscribers
291 photos
10 videos
15 files
148 links
Пишу о книгах, лидерстве, технологиях, opensource, своих проектах и наверное чем-то ещё. Ну и репосты IT приколямб.
Download Telegram
#python

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

И первая тема: менеджеры контекста и инструкции with.


Наверняка вы хоть раз писали что-то типа
with open("model.pickle", "br") as f:
model = pickle.read(f)
Это стандартный путь работы с файлами в python. Зачем так делать? Чтобы гарантировать закрытие контекста файла. В файлах используются специальные дескрипторы, и если их не поставить, то файл может поламаться.

Эта штука называется контекстом. Открытие файла - открывает контекст f, а функция f.close(). И вот чтобы не париться со всем этим есть конструкция менеджера контекста и инструкция with которая упрощает работу с ним.

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

Вы можете мутить свои менеджеры контекстов, взаимодействующие с with для этого нужно реализовать функции __enter__(self) для открытия контекста и __exit__(self, exc_type, exc_val, exc_tb) для закрытия.

Есть и другой способ. Его просто примером покажу. Там декоратор и фабричная функция. Подходы эквивалентны выбирать, отталкиваясь от кодстайла.

from contextlib import contextmanager 

@contextmanager
def managed_file(name):
try:
f = open(name, 'w')
yield f
finally:
f.close()
#python

Ещё немного снипитов кода упертых из книги Дэна Байдера.

Я не знал, что при возвращение внутренней функции, она запоминает состояние внешней. Теперь знаю, даже представил себе, как это работает.

Вот пара примеров:
def get_speak_func(text, volume):
def whisper():
return text.lower() + '...'
def yell():
return text.upper() + '!'
if volume > 0.5:
return yell
else:
return whisper
>>> get_speak_func('Привет, Мир', 0.7)()
'ПРИВЕТ, МИР!'

Здесь запоминается текст, переданный при получении внутренней функции.

Вот еще наглядный пример:
def make_adder(n):
def add(x):
return x + n
return add
>>> plus_3 = make_adder(3)
>>> plus_5 = make_adder(5)
>>> plus_3(4)
7
>>> plus_5(4)
9


Практическое применение - создание фабрики функций. По сути внешняя конфигурирует внутреннюю. Возможность интересная и, вероятно, в определенных обстоятельствах полезная. Я же обычно предпочитаю делать объекты-калькуляторы. У которых состояние конфигурируется через внутренние атрибуты и есть метод расчёта calc(self, *args). Мне кажется такой подход более явным , а
Явное лучше, чем неявное.
👍2