0

I define a variable in a function, and I want to use this variable in inner function defined in the outer function. However, there is an error: this variable referenced before assignment. I don't know why.

class Solution(object):
    def findItinerary(self, tickets):
        """
        :type tickets: List[List[str]]
        :rtype: List[str]
        """
        length = len(tickets)
        visit = [1 for i in range(length)]
        tmp = []
        result = []

        def dfs(tickets, ticket):
            if len(tmp) == length:
                tmp.append(ticket[1])
                if len(result) == 0 or (result != [] and result[1:] > tmp[1:]):
                   result = tmp
                tmp.pop()
                return
            for i in range(length):
                if visit[i] == 1 and ticket[1] == tickets[i][0]:
                    tmp.append(ticket[1])
                    visit[i] = 0
                    dfs(tickets, tickets[i])
                    visit[i] = 1
                    tmp.pop()

        for count in range(length):
            if tickets[count][0] == "JFK":
                visit[count] = 0
                tmp.append(tickets[count][0])
                dfs(tickets, tickets[count])
                tmp.pop()
                visit[count] = 1
        return result

"result" is the variable. And error is like this:

UnboundLocalError: local variable 'result' referenced before assignment

if I replace

result = tmp

with

del result[:]
result.extend(tmp)

Then it works. And I am so confused about this.

Mel
  • 5,837
  • 10
  • 37
  • 42
Danny Wang
  • 35
  • 2
  • 1
    Note that assignment makes `result` a local variable. Your change removes the assignment which makes `result` a global variable (in `dfs`). – skyking Apr 28 '17 at 09:59
  • Possible duplicate of http://stackoverflow.com/questions/37473666/variable-scope-in-python-nested-function – PM 2Ring Apr 28 '17 at 10:10
  • What skyking said. A cleaner way to fix this is to use a slice assignment to copy the contents of `tmp` to the `result` list: `result[:] = tmp`. This works because it just mutates the existing `result` list object, it's not assigning a new `tmp` list to the old `result` name. – PM 2Ring Apr 28 '17 at 10:14
  • Does this answer your question? [Variable scope in Python nested function](https://stackoverflow.com/questions/37473666/variable-scope-in-python-nested-function) – user202729 Feb 01 '21 at 01:06

1 Answers1

0

By setting result you are telling python that it is a local variable, which will be defined in the inner-most scope. If you are using python3, you can use nonlocal for using the same variable as the outer scope. In python2 this variable is essential "read-only" and you can't assign to it within the inner scope.

From the documentation:

A special quirk of Python is that – if no global statement is in effect – assignments to names always go into the innermost scope. Assignments do not copy data — they just bind names to objects. The same is true for deletions: the statement del x removes the binding of x from the namespace referenced by the local scope. In fact, all operations that introduce new names use the local scope: in particular, import statements and function definitions bind the module or function name in the local scope.

The global statement can be used to indicate that particular variables live in the global scope and should be rebound there; the nonlocal statement indicates that particular variables live in an enclosing scope and should be rebound there.

Community
  • 1
  • 1
Dean Fenster
  • 2,345
  • 1
  • 18
  • 27