numba.closure

This module provides support for closures and inner functions.

@autojit def outer():

a = 10 # this is a cellvar

@jit(‘void()’) def inner():

print a # this is a freevar

inner() a = 12 return inner

The ‘inner’ function closes over the outer scope. Each function with cellvars packs them into a heap-allocated structure, the closure scope.

The closure scope is passed into ‘inner’ when called from within outer.

The execution of ‘def’ creates a NumbaFunction, which has itself as the
m_self attribute. So when ‘inner’ is invoked from Python, the numba wrapper function gets called with NumbaFunction object and the args tuple. The closure scope is then set in NumbaFunction.func_closure.

The closure scope is an extension type with the cellvars as attributes. Closure scopes are chained together, since multiple inner scopes may need to share a single outer scope. E.g.

def outer(a):
def inner(b):
def inner_inner():
print a, b

return inner_inner

return inner(1), inner(2)

We have three live closure scopes here:

scope_outer = { ‘a’: a } # call to ‘outer’ scope_inner_1 = { ‘scope_outer’: scope_outer, ‘b’: 1 } # call to ‘inner’ with b=1 scope_inner_2 = { ‘scope_outer’: scope_outer, ‘b’: 2 } # call to ‘inner’ with b=2

Function ‘inner_inner’ defines no new scope, since it contains no cellvars. But it does contain a freevar from scope_outer and scope_inner, so it gets scope_inner passed as first argument. scope_inner has a reference to scope outer, so all variables can be resolved.

These scopes are instances of a numba extension class.

class numba.closure.ClosureCompilingMixin(*args, **kwargs)

Runs during late specialization.

  • Instantiates the closure scope and makes the necessary assignments
  • Rewrites local variable accesses to accesses on the instantiated scope
  • Instantiate function with closure scope
assign_closure(func_call, node)

Assign closure to its name. NOT USED, already happened in CFG

visit_ClosureNode(node)

Compile the inner function.

visit_InstantiateClosureScope(node)

Instantiate a closure scope.

After instantiation, assign the parent scope and all function arguments that belong in the scope to the scope.

visit_Name(node)

Resolve cellvars and freevars

class numba.closure.ClosureMixin

Handles closures during type inference. Mostly performs error checking for closure signatures.

Generates ClosureNodes that hold inner functions. When visited, they do not recurse into the inner functions themselves!

class numba.closure.ClosureTypeInferer(*args, **kwargs)

Runs just after type inference after the outer variables types are resolved.

  1. run type inferencer on inner functions
  2. build scope extension types pre-order
  3. generate nodes to instantiate scope extension type at call time
update_closures(func_def, scope_type, ext_type)

Patch closures to get the closure scope as the first argument.

numba.closure.lookup_scope_attribute(cur_scope, var_name, ctx=None)

Look up a variable in the closure scope

numba.closure.process_closures(context, outer_func_def, outer_symtab, **kwds)

Process closures recursively and for each variable in each function determine whether it is a freevar, a cellvar, a local or otherwise.

Previous topic

numba.cfg

Next topic

numba.decorators

This Page