LINUX.ORG.RU

История изменений

Исправление Virtuos86, (текущая версия) :

Шо, опять объяснять?
Не понял, про какие лямбды идет речь, как и этот пассаж:

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

Википедия описывает RAII так.
Юзкейс для with как менеджера контекста иллюстрирует типовой пример:

f = open("file")
try:
    # выполняем какие-то манипуляции с открытым файлом
    …
finally:
    # ветка `finally` гарантированно выполняется, и мы гарантированно закрываем файл
    f.close()
Это идиоматичный код: захватываем ресурс, работаем с ним и гарантированно освобождаем его, исключая порчу данных. Но это тупой код (в ветке `finally` механическое набивание освобождения ресурса), и для этого используется констукция try/except/finally, чье прямое назначение всё-таки отлов исключений. Налицо необходимость в новой фиче, осенило ГВР, и он выдал на-гора не только with, но и механизм для создания собственных вундервафлей для работы с произвольными пользовательскими ресурсами с помощью этого with. И назвали этот механизм context manager.
Вышеприведенный пример, будучи переписан, выглядит так:
with f = open("file"):
    # выполняем какие-то манипуляции с открытым файлом
    …
Как только заканчивается блок with, файл будет автоматически закрыт. То есть здесь файл сам по себе выступает как менеджер контекста.
Понятное дело, под капотом всё та же кака с try/finally, но ее нужно писать только один раз — в самом менеджере контекста, а в остальном коде будет ляпота (осторожно, паста):
@contextmanager
def stdout_redirected(new_stdout):
    save_stdout = sys.stdout
    sys.stdout = new_stdout
    try:
        yield None
    finally:
        sys.stdout = save_stdout

with open(filename, "w") as f:
    with stdout_redirected(f):
        print "Hello world"
Открываем файл, перенаправляем в него стандартный поток вывода, печатаем в него «привет мир», возвращаем всё обратно, как было, закрываем файл. И всё это абсолютно в рамках exception safety. По-моему, очень классно.
Да, здесь нет «сахарку» из фри-бейсика, придется явно писать f.metod() и т.д.

Исходная версия Virtuos86, :

Шо, опять объяснять?
Википедия описывает RAII так.
Юзкейс для with как менеджера контекста иллюстрирует типовой пример:

f = open("file")
try:
    # выполняем какие-то манипуляции с открытым файлом
    …
finally:
    # ветка `finally` гарантированно выполняется, и мы гарантированно закрываем файл
    f.close()
Это идиоматичный код: захватываем ресурс, работаем с ним и гарантированно освобождаем его, исключая порчу данных. Но это тупой код (в ветке `finally` механическое набивание освобождения ресурса), и для этого используется констукция try/except/finally, чье прямое назначение всё-таки отлов исключений. Налицо необходимость в новой фиче, осенило ГВР, и он выдал на-гора не только with, но и механизм для создания собственных вундервафлей для работы с произвольными пользовательскими ресурсами с помощью этого with. И назвали этот механизм context manager.
Вышеприведенный пример, будучи переписан, выглядит так:
with f = open("file"):
    # выполняем какие-то манипуляции с открытым файлом
    …
Как только заканчивается блок with, файл будет автоматически закрыт. То есть здесь файл сам по себе выступает как менеджер контекста.
Понятное дело, под капотом всё та же кака с try/finally, но ее нужно писать только один раз — в самом менеджере контекста, а в остальном коде будет ляпота (осторожно, паста):
@contextmanager
def stdout_redirected(new_stdout):
    save_stdout = sys.stdout
    sys.stdout = new_stdout
    try:
        yield None
    finally:
        sys.stdout = save_stdout

with open(filename, "w") as f:
    with stdout_redirected(f):
        print "Hello world"
Открываем файл, перенаправляем в него стандартный поток вывода, печатаем в него «привет мир», возвращаем всё обратно, как было, закрываем файл. И всё это абсолютно в рамках exception safety. По-моему, очень классно.
Да, здесь нет «сахарку» из фри-бейсика, придется явно писать f.metod() и т.д.