1

My example below. I have tried adding global to the variable that I want to change but doesn't help. The error I'm getting is in the comment.

def getNumOfSwapsToSort(array):
    sorted = array.copy()
    sorted.sort()

    swaps = 0

    def swap():
        currentSwaps = 0
        for i, el in enumerate(array):
            if ((len(array) - 1) == i) and currentSwaps != 0:
                swap()

            elif el != sorted[i]:
                idx = sorted.index(el)
                temp = array[idx]
                array[idx] = el
                array[i] = temp
                # UnboundLocalError: local variable 'swaps' referenced before assignment
                # if I use global swaps, then NameError: name 'swaps' is not defined
                swaps += 1
                currentSwaps += 1

    swap()

    return swaps
Karolis
  • 143
  • 3
  • 12
  • 1
    An almost identical question: https://stackoverflow.com/questions/2609518/unboundlocalerror-with-nested-function-scopes – natka_m Feb 17 '20 at 18:19
  • 1
    Possible duplicate of [UnboundLocalError with nested function scopes](https://stackoverflow.com/questions/2609518/unboundlocalerror-with-nested-function-scopes) – wjandrea Feb 17 '20 at 19:00

2 Answers2

3

The swaps variable in your code is not global, it's nonlocal. It was defined in the enclosing function getNumOfSwapsToSort(), not in the global namespace.

Your other function, swap(), has access to this nonlocal variable, but the variable is protected from being edited from the inner function. If you try to edit or overwrite it, it's going to be treated as a new, local variable - hence the UnboundLocalError you're getting.

Try using the nonlocal statement:

nonlocal swaps
swaps += 1

Here's an article with a few simple examples which explain the concept of closure in Python.

natka_m
  • 1,297
  • 17
  • 22
1

swaps isn't a global, it's in getNumOfSwapsToSort, which is the parent scope of swap. So use a nonlocal declaration.

def swap():
    nonlocal swaps
    ...
wjandrea
  • 28,235
  • 9
  • 60
  • 81