python - 我们如何将 Python 上下文管理器 "associate"指向出现在其 block 中的变量?

标签 python pymc3 contextmanager

据我了解,上下文管理器在 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)

并提到这具有关联变量 alphabetasigmamuY_obs 到模型 basic_model。

我想了解这种机制是如何运作的。在explanations of我发现的上下文管理器,我没有看到任何暗示上下文 block 中定义的变量或对象如何以某种方式“关联”到上下文管理器的信息。看起来库(PyMC3)以某种方式可以访问“当前”上下文管理器,因此它可以在幕后将每个新创建的语句关联到它。但是图书馆如何才能访问上下文管理器?

最佳答案

PyMC3 通过维护一个 thread local variable 来做到这一点作为 Context 类中的类变量Model 继承自 Context

每次您在模型上调用 with 时,当前模型都会被推送到特定于线程的上下文堆栈中。因此,堆栈的顶部始终指的是用作上下文管理器的最里面(最近)的模型。

Context(因此 Model)有一个 .get_context() 类方法获取上下文堆栈的顶部。

Distribution 调用 Model.get_context()当它们被创建以将自己与最内层的模型相关联时。

简而言之:

  1. with modelmodel 压入上下文堆栈。这意味着在 with block 内部,type(model).contextsModel.contexts,或 Context.contexts 现在包含 model 作为其最后(最顶层)元素。
  2. Distribution.__init__() 调用 Model.get_context()(注意大写 M),它返回上下文堆栈的顶部。在我们的例子中,这是 model。上下文堆栈是线程本地的(每个线程有一个),但它不是特定于实例的。如果只有一个线程,那么也只有一个上下文堆栈,而不管模型的数量。
  3. 退出上下文管理器时。 model 从上下文堆栈中弹出。

关于python - 我们如何将 Python 上下文管理器 "associate"指向出现在其 block 中的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51849395/

相关文章:

python - 将两个上下文管理器合二为一

python - 返回异常而不是抛出异常

python - 从 pymc2 到 PyMC3 的 CAR 模型

python - 如何使用 Pandas 将字符串转换为数据表excel?

python - 如何使用 Pymc3 模拟有偏向的 6 面骰子?

python - 如何实现最大似然估计类型 2?

python - 如何在异步循环关闭之前等待对象的 __del__ 完成?

python - 如何访问上下文管理器的属性?

python - 使用加密的 PEM 客户端证书调用 REST api

python - 按条件删除重复的元组对