如果使用with
语句调用,我想创建一个也可以充当上下文管理器的函数。示例用法是:
# Use as function
set_active_language("en")
# Use as context manager
with set_active_language("en"):
...
这与标准函数open
的使用方式非常相似。
以下是我提出的解决方案:
active_language = None # global variable to store active language
class set_active_language(object):
def __init__(self, language):
global active_language
self.previous_language = active_language
active_language = language
def __enter__(self):
pass
def __exit__(self, *args):
global active_language
active_language = self.previous_language
此代码不是线程安全的,但这与问题无关。
我不喜欢这个解决方案的是,类构造函数假装是一个简单的函数,仅用于它的副作用。
有更好的方法吗?
请注意,我尚未测试此解决方案。
更新:我不想将函数和上下文管理器拆分为单独的实体的原因是命名。基本上,函数和上下文管理器做同样的事情,因此为两者使用一个名称似乎是合理的。如果我想将它保持独立,则命名上下文处理器会有问题。它应该是什么? active_language
?此名称可能(并将与变量名称)冲突。 override_active_language
可能会有用。
答案 0 :(得分:2)
技术上不,你不能这样做。但是你可以把它弄得很好,以至于人们(没有过分思考它)也不会注意到。
def set_active_language(language):
global active_language
previous_language = active_language
active_language = language
class ActiveScope(object):
def __enter__(self):
pass
def __exit__(self, *args):
global active_language
active_language = previous_language
return ActiveScope()
当用作函数时,ActiveScope
类只是一个稍微浪费的无操作。
答案 1 :(得分:0)
希望有人会证明我错了,但我认为答案是不:没有别的办法。而且,您选择的方法的另一个缺点是,当与160px
语句中的其他上下文管理器一起使用时,它可能会出错。 CM的预期副作用是在对象构造上执行的,而不是在预期的with a, b, c:
方法中执行。
为了能够做你想做的事,你必须从类构造函数内部知道它是在__enter__
语句中初始化为上下文管理器,还是简单地作为函数调用。据我所知,没有办法收集,甚至没有with
模块。