0

I wrote some code wrong and found my bug, which is that I reassigned a mutable variable locally. However, the observed behavior confused me.

Here is a minimal example:

import numpy as np
n = 138

MQ = np.zeros((n, 0))

def calc(v):
  print(v)

  #do some complicated math
  if v % 16 == 3:
    q = np.random.random((n, 1))
    MQ = np.hstack((MQ, q))
  else:
    #do some complicated math and eventually call function recursively
    pass

  calc(v-1)

calc(700)

As you can see, MQ is bound to a numpy array initially of size (138, 0) and the recursive function stacks some (138,1) arrays onto it when some complicated math things happen, the intention being to find some valid 138 dimensional vectors that solve the complicated math problem.

Of course, the bug here is that MQ is reassigned each recursion and will never mutate correctly because nothing in the code actually mutates it.

However, the behavior that I would expect from this example is, that on every recursion, the calc() function does not have the new incarnation of the variable MQ, instead it has the version of MQ that it closed over, which is an 138x0 array that was reassigned in the previous recursive call, but the original was never touched.

Instead, the behavior observed when running this example is UnboundLocalError: local variable 'MQ' referenced before assignment. Why is this? Clearly the recursive function closes over MQ, how can it be unbound?

aestrivex
  • 5,170
  • 2
  • 27
  • 44
  • If a variable is on the left side of an assignment anywhere in a function, it is seen as local everywhere in that function (if not explicitly declared otherwise). If a variable is local is decided when the function is compiled to byte code. – Michael Butscher Dec 07 '22 at 21:40

0 Answers0