with
ステートメントで呼び出された場合、コンテキストマネージャとしても機能する関数を作成したいと考えています。使用例は次のようになります。これは、標準機能open
が使用されている方法と非常に似てコンテキストマネージャを関数として使用する
# Use as function
set_active_language("en")
# Use as context manager
with set_active_language("en"):
...
。
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
このコードはスレッドセーフではありませんが、これは問題とは関係ありません。
ここで私が思いついた解決策です。
私はこの解決策について気に入らないのは、クラスコンストラクタが単純な関数であると主張し、その副作用に対してのみ使用されるということです。
これを行うより良い方法はありますか?
このソリューションはテストしていません。
更新:私が機能とコンテキストマネージャを別々のエンティティに分割したくない理由は、命名です。関数とコンテキストマネージャは基本的に同じことを行います。したがって、両方に1つの名前を使用することは合理的です。コンテキストプロセッサの名前を付けることは、別にしておきたい場合には問題になります。それは何でしょうか? active_language
?この名前は変数名と衝突する可能性があります。しかし、override_active_language
が動作する可能性があります。
あなたは 'contextlib'から' contextmanager'デコレータを使うことができますが、あなたの関数はジェネレータでなければなりません。 https://docs.python.org/2/library/contextlib.html#contextlib.contextmanager –
'open'は、オブジェクトの参照カウントが0になったときにクリーンアップされる状態(開いているファイルハンドル)を保持します。 'open( 'foo')'(何にも割り当てることなく)は、その副作用のためだけに有用です。だから、質問... 'foo = set_active_language(); del foo'を元の言語に戻したいですか?もしそうなら、コールは 'open'のように状態を運んでいます。 – tdelaney
あなたは非常に疑わしい価値のあるものを設計/実装しようとしています。それについて考える:ユーザーは本当にそれが必要なのか?それがあなたのコードを役に立つものにしていますか?疑わしい。 私はクラス(オブジェクトではありません!)が関数ANDコンテクストマネージャーであると期待していた最も驚くべきことの最後のことです。関数とコンテキストマネージャを別々のエンティティにする。既存のプラクティスに従う:https://github.com/django/django/blob/master/django/utils/translation/__init__py#L170 – Andrey