Context
特定の計算が実行されるコンテキストへのアクセス ポイントとして機能するインスタンスに大きく依存するアプリケーションがあります。
Context
インスタンスへのアクセスを提供したい場合は、次のことができます。
- に頼る
global
Context
を必要とするすべての関数にパラメーターとして渡す
むしろglobal
変数を使用したくありません。インスタンスをすべての関数に渡すのContext
は面倒で冗長です。
計算をどのように「非表示にしますが、アクセスできるようにしますContext
か? 」
たとえば、Context
さまざまなデータに基づいて惑星の状態 (位置と速度) を単純に計算するとします。
class Context(object):
def state(self, planet, epoch):
"""base class --- suppose `state` is meant
to return a tuple of vectors."""
raise NotImplementedError("provide an implementation!")
class DE405Context(Context):
"""Concrete context using DE405 planetary ephemeris"""
def state(self, planet, epoch):
"""suppose that de405 reader exists and can provide
the required (position, velocity) tuple."""
return de405reader(planet, epoch)
def angular_momentum(planet, epoch, context):
"""suppose we care about the angular momentum of the planet,
and that `cross` exists"""
r, v = context.state(planet, epoch)
return cross(r, v)
# a second alternative, a "Calculator" class that contains the context
class Calculator(object):
def __init__(self, context):
self._ctx = context
def angular_momentum(self, planet, epoch):
r, v = self._ctx.state(planet, epoch)
return cross(r, v)
# use as follows:
my_context = DE405Context()
now = now() # assume this function returns an epoch
# first case:
print angular_momentum("Saturn", now, my_context)
# second case:
calculator = Calculator(my_context)
print calculator.angular_momentum("Saturn", now)
もちろん、すべての操作を「コンテキスト」に直接追加することもできますが、それは適切ではありません。
実際には、Context
は惑星の位置を計算するだけではありません! より多くのことを計算し、多くのデータへのアクセス ポイントとして機能します。
では、私の質問をより簡潔にするために、多くのクラスからアクセスする必要があるオブジェクトをどのように処理しますか?
私は現在探索しています: python のコンテキスト マネージャーですが、あまり運がありません。また、プロパティ「コンテキスト」をすべての関数に直接動的に追加することも考えました(関数はオブジェクトであるため、任意のオブジェクトへのアクセスポイントを持つことができます)。
def angular_momentum(self, planet, epoch):
r, v = angular_momentum.ctx.state(planet, epoch)
return cross(r, v)
# somewhere before calling anything...
import angular_momentum
angular_momentum.ctx = my_context
編集
素晴らしいことは、次のようなwith
ステートメントで「計算コンテキスト」を作成することです。
with my_context:
h = angular_momentum("Earth", now)
もちろん、単純に次のように記述すれば、すでにそれを実行できます。
with my_context as ctx:
h = angular_momentum("Earth", now, ctx) # first implementation above
たぶん、戦略パターンでこれのバリエーションですか?