Может ли функция вести себя как функция *и* контекстный менеджер?

Я понимаю, как можно расширить объект, чтобы его также можно было использовать в качестве менеджера контекста. Я также понимаю, как можно легко создать диспетчер контекста из функции (генератора), используя contextlib.

Однако можно ли написать функцию, которая будет вести себя как функция при использовании в качестве функции,

foo = make_foo()

и как диспетчер контекста при использовании в качестве диспетчера контекста,

with make_foo() as foo:
  ...

Оглядевшись вокруг, я бы сказал, что это невозможно, но разве не так ведет себя функция open? Возможно ли такое поведение только для встроенных функций или его также можно достичь с помощью кода Python?


person user209974    schedule 17.03.2020    source источник
comment
Когда вы пишете with make_foo() as foo:, менеджером контекста является не сама функция, а любой объект, возвращаемый функцией. Единственное требование состоит в том, чтобы возвращаемый объект имел методы __enter__() и __exit__(). Таким образом, вы не могли вернуть int или str из функции, а также использовать ее в качестве диспетчера контекста, но вы могли определить подкласс этих типов, который будет работать.   -  person jasonharper    schedule 18.03.2020
comment
В операторе with не происходит ничего сверхъестественного. После того, как make_foo() возвращает объект (назовем его obj), foo привязывается к obj.__enter__(), а не к самому obj. Именно возвращаемое значение make_foo, а не само make_foo действует как менеджер контекста.   -  person chepner    schedule 18.03.2020
comment
Обычно методы __enter__ объектов, возвращаемых open, просто возвращают self.   -  person chepner    schedule 18.03.2020
comment
@ user209974 ... вы просите что-то вроде этого: pastebin.com/39t6H9X5   -  person Todd    schedule 18.03.2020