Variable scoping for collect_vertex_marginals

Hi again,
This is more a python related question, but I'm asking here hoping somebody had a similar issue and worked it out.
I need to collect vertex marginals during equilibrate and when I do it in my python console everything works just fine (as in the cookbook):

pv = [None] * len(state.get_levels())

def collect_marginals(s):
  global pv
  pv = [sl.collect_vertex_marginals(pv[l]) for l, sl in enumerate(s.get_levels())]

gt.mcmc_equilibrate(state, force_niter=10000, mcmc_args=dict(niter=10), callback=collect_marginals)

as far as understand, every time sl.collect_vertex_marginals is called, it takes as argument the histogram calculated in the previous iterations.
My problem is that when I put this code into a function that is imported as a module, scoping is broken and I get an error like

NameError: name 'pv' is not defined

Shortly, I have the function nsbm in file _nsbm.py:

def nsbm(…):
  […]
  pv = [None] * len(state.get_levels())

  def collect_marginals(s):
    global pv
    pv = [sl.collect_vertex_marginals(pv[l]) for l, sl in enumerate(s.get_levels())]

  gt.mcmc_equilibrate(state, force_niter=10000, mcmc_args=dict(niter=10), callback=collect_marginals)

which is imported

from ._nsbm import nsbm

by the __init__.py of the package module (named tools), then imported by the main

from . import tools as tl

the directory structure of the package is (among others)

scanpy/tools/_nsbm.py
scanpy/tools/__init__.py
scanpy/__init__.py

as far as I understand callback function passed to mcmc_equilibrate is not supposed to return anything, collect_vertex_marginals returns the histogram summing the current to the previous. I think I can't pass pv as an argument to the callback as it becomes local to the function.
Of course, I'm now reading about variable scoping in python, but if you have any hint it would be greatly appreciated.
Thanks

d

You're looking for the nonlocal keyword, instead of global. See here:

https://docs.python.org/3/reference/simple_stmts.html#grammar-token-nonlocal-stmt

Thanks, for the time being I've solved with a try/except within the function, so that

def foo():
  global pv
  […]
  try:
    pv = [sl.collect_vertex_marginals(pv[l]) for l, sl in enumerate(s.get_levels())]
  except NameError:
   pv = [None] * len(state.get_levels())

(in fact I've tried to delete the post from the nabble interface...)
Best,

d