with — заблуждения об управлении контекстом в python

Опубликовано: 2011-11-11
Теги: python, context-managers, with

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

Еще раз копирую пример здесь:

class Logger(object):
    def __init__(self, val):
        self.val = val
        print "%d :: __init__" % self.val

    def __enter__(self):
        print "%d :: __enter__" % self.val

    def __exit__(self, exc_type, exc_val, exc_tb):
        print "%d :: __exit__ " % self.val

for i in xrange(5):
    with  Logger(i) as log:
        pass

Почти ни у кого не возникает вопросов в какой момент срабатывает __enter__, а в какой __exit__ однако, далеко не все понимают что эти два метода НЕ являются деструкторами и конструкторами класса (в данном случае Logger), и соответственно не являются заменой методов __new__ и __del__, а значит оператор with может быть применен к экземпляру класса Logger более одного раза.

Вот так:

logger = Logger(0)

for i in xrange(5):
    logger.val += 1
    with logger as log:
        pass

Есть еще одно заблуждение, и оно в принципе обосновано ибо тут уже начинают немного пудрить мозги примеры. Многие думают, что внутрь контекста идет обязательно инстанс того объекта, который был передан в with, то есть в переменной log обязательно будет инстанс класса Logger. Однако, это не так. В контекст попадает любой объект который возвращает __enter__, и в примере выше переменная log будет равна None, более подробный пример можете посмотреть по ссылке выше, хоть он и бесполезен в python 2.7.

Далее, где можно применить управление контекстом кроме банального открытия файлов:

Примеров очень много, и применение зависит только от фантазии программиста.

blog comments powered by Disqus

Блог

Работает на движке cyrax. В качестве шаблона модифицированная тема "Clean Minimal" от themelab.com.