如何在 lambda 中使用上下文管理器?接受黑客攻击。推迟对 lambda 的错误使用的看法。
我知道我能做到:
def f():
with context():
return "Foo"
但我想做这样的事情:
lambda: with context(): "Foo"
你不能用表达式代替
with
所做的工作,不。也没有任何技巧可以帮助您实现这一目标,因为无法在表达式中处理异常和终结。
那是因为您只能在 lambda 中使用一个表达式。
with
是一个 陈述,而不是表达式。您必须将其替换为异常处理 (try..except..finally
) 并调用 __enter__
和 __exit__
方法(存储 __exit__
方法 first)。但是,异常处理只能通过语句来完成,因为异常会立即结束当前表达式。请参阅 lambda 中的 Python Try Catch 块。
您唯一的选择是坚持使用正确的函数。
ContextDecorator
,然后
with
语句和 lambda
表达式都可以工作,因为 lambda 可以使用装饰器模式。示例
from contextlib import ContextDecorator
def f(x):
"""Just prints the input, but this could be any arbitrary function."""
print(x)
class mycontext(ContextDecorator):
def __enter__(self):
f('Starting')
return self
def __exit__(self, *exc):
f('Finishing')
return False
with mycontext():
f('The bit in the middle')
mycontext()(lambda: f('The bit in the middle'))()
with
语句上使用包装函数,如下所示:
from typing import TypeVar
from contextlib import AbstractContextManager
from collections.abc import Callable
T = TypeVar("T"); V = TypeVar("V")
def _with(ctx: AbstractContextManager[T], action: Callable[[T], V]) -> V:
with ctx as c: return action(c)
_with(context(), lambda c: "Foo")