据我了解,上下文管理器在 Python 中用于定义对象的初始化和完成代码片段(__enter__
和 __exit__
)。
但是,在 tutorial for PyMC3他们展示了以下上下文管理器示例:
basic_model = pm.Model()
with basic_model:
# Priors for unknown model parameters
alpha = pm.Normal('alpha', mu=0, sd=10)
beta = pm.Normal('beta', mu=0, sd=10, shape=2)
sigma = pm.HalfNormal('sigma', sd=1)
# Expected value of outcome
mu = alpha + beta[0]*X1 + beta[1]*X2
# Likelihood (sampling distribution) of observations
Y_obs = pm.Normal('Y_obs', mu=mu, sd=sigma, observed=Y)
并提到这具有关联变量 alpha
、beta
、sigma
、mu
和Y_obs
到模型 basic_model。
我想了解这种机制是如何运作的。在explanations of我发现的上下文管理器,我没有看到任何暗示上下文 block 中定义的变量或对象如何以某种方式“关联”到上下文管理器的信息。看起来库(PyMC3)以某种方式可以访问“当前”上下文管理器,因此它可以在幕后将每个新创建的语句关联到它。但是图书馆如何才能访问上下文管理器?
最佳答案
PyMC3 通过维护一个 thread local variable 来做到这一点作为 Context
类中的类变量。 Model
继承自 Context
。
每次您在模型上调用 with
时,当前模型都会被推送到特定于线程的上下文堆栈中。因此,堆栈的顶部始终指的是用作上下文管理器的最里面(最近)的模型。
Context
(因此 Model
)有一个 .get_context()
类方法获取上下文堆栈的顶部。
Distribution
调用 Model.get_context()
当它们被创建以将自己与最内层的模型相关联时。
简而言之:
with model
将model
压入上下文堆栈。这意味着在with
block 内部,type(model).contexts
或Model.contexts
,或Context.contexts
现在包含model
作为其最后(最顶层)元素。Distribution.__init__()
调用Model.get_context()
(注意大写M
),它返回上下文堆栈的顶部。在我们的例子中,这是model
。上下文堆栈是线程本地的(每个线程有一个),但它不是特定于实例的。如果只有一个线程,那么也只有一个上下文堆栈,而不管模型的数量。- 退出上下文管理器时。
model
从上下文堆栈中弹出。
关于python - 我们如何将 Python 上下文管理器 "associate"指向出现在其 block 中的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51849395/