5

Could someone please explain the following result in Python?

When running the following snippet of code, Python throws an error, saying that the variable x was referenced before assignment:

x = 1

def increase_x():
    x += 1

increase_x()

The solution, of course, would be to include the line global x after the function declaration for increase_x.

However, when running this next snippet of code, there is no error, and the result is what you expect:

x = [2, -1, 4]

def increase_x_elements():
    for k in range(len(x)):
        x[k] += 1

increase_x_elements()

Is this because integers are primitives in Python (rather than objects) and so x in the first snippet is a primitive stored in memory while x in the second snippet references a pointer to a list object?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Ryan
  • 7,621
  • 5
  • 18
  • 31
  • 3
    *Everything in Python is an object*, even integers. The difference is because one is mutable (list) and one is immutable (integer). – Ffisegydd Jan 06 '15 at 09:46
  • 1
    This question explains the reason behind it. http://stackoverflow.com/questions/21456739/unboundlocalerror-local-variable-l-referenced-before-assignment-python http://stackoverflow.com/questions/9264763/unboundlocalerror-in-python – doptimusprime Jan 06 '15 at 09:52

2 Answers2

6

As Ffisegydd points out, there is no such thing as a primitive in Python: everything is an object.

You should however note that you are doing two completely different things in those two snippets. In the first, you are rebinding x to the value of x+1. By attempting to assign to x, you've made it locally scoped, so your reference to x+1 fails.

In the second snippet, you are modifying the contents of x, rather than rebinding it. This works because lists are mutable, but the difference is not mutable vs immutable but mutating vs rebinding: rebinding a mutable object would fail just as doing so with an integer does.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • 1
    This is why I didn't try to actually answer because 1) I haven't had any coffee and 2) I wasn't sure of how to explain it fully/whether I was totally correct :P – Ffisegydd Jan 06 '15 at 09:56
0

In Python, variables that are only referenced inside a function are implicitly global. That's why code below works.

x = 1

def increase_x():
    print(x + 1)

increase_x()

However, If a variable is assigned a value anywhere within the function’s body, it’s assumed to be a local unless explicitly declared as global. In your first example, because of this x += 1 assignment, x isn't global anymore.

Jzou
  • 1,225
  • 3
  • 11
  • 22