我有一个应用程序严重依赖一个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
也许这是策略模式的变体?