python - 如何制作一个也可用作上下文管理器的 python 方法?
问题描述
在我正在构建的图形 API 中,我想创建一个也可以用作上下文管理器的方法:
该方法当前如下所示:
class Gfx:
def __init__(self):
self._fill = None
def fill(self, color):
self._fill = color
我可以制作一个在使用后恢复状态的上下文管理器,如下所示:
class Gfx:
def __init__(self):
self._fill = None
@contextmanager
def fill(self, color):
"""Allow user to set fill color, then restore it"""
old_fill = self._fill
self._fill = color
yield
self._fill = old_fill
但是我怎样才能使这两种方式都起作用,这取决于它的调用方式?
>>> gfx = Gfx()
>>> gfx.fill("red") # use as ordinary method
>>> print(self._fill)
"red"
>>> with gfx.fill("blue") # use as context manager
... print(gfx._fill)
"blue"
>>> print(gfx._fill)
"red"
解决方案
您需要混合使用这些方法;有一个 this 被调用的函数,返回一个上下文管理器,其中上下文管理器在不用于with
. 类似于以下内容:
class Gfx:
def __init__(self):
self._fill = None
@contextmanager
def _fillctx(self, old_fill):
try:
yield
finally:
self._fill = old_fill
def fill(self, color):
"""Allow user to set fill color, then restore it"""
old_fill = self._fill
self._fill = color
return self._fillctx(old_fill)
当不使用 调用时with
,它设置self._fill
并返回一个从未使用过的上下文管理器。当使用 调用时with
,它将在调用该上下文管理器的self._fill
时重置。__exit__
需要明确的是,最好只使用单独的方法,因此您的“普通方法”方法更有效,并且您的上下文管理器方法可以更安全一些(实际上__enter__
按照您的预期进行设置工作,缩小范围会阻止__exit__
被调用的竞争条件的窗口)。
推荐阅读
- d3.js - D3v5 自定义捆绑包
- nodatime - 与 NodaTime 一起使用的其他软件包
- python - 我的 postgresql 数据库不响应 python 命令
- java - 如何使用菜单中的单选按钮更改文本视图的文本和背景颜色
- python - 当并非所有角都可见时执行透视变换python openCV
- javascript - 街机字体建议
- julia - 具有大 xtick 标签编号的 JuliaLang 绘图显示有太多的科学计数法数字和格式错误的指数
- git - 重访:将远程重置为某个提交
- chef-infra - 是否可以在食谱中的 .kitchen.yml 中找到平台或套件名称?
- powerbi - 如何使用用户输入开发表格,如excel表我可以输入值并且它可以计算值?