UnboundLocalError: local variable 'L' referenced before assignment Python

Question:

when trying to compile the code below I get this error

UnboundLocalError: local variable 'L' referenced before assignment

Can someone explain why ? Isn’t a global variable assigned before anything else?

My Python version is 2.7.3

#!/usr/bin/env python

import pygame
from pygame.locals import *
from sys import exit
import random
import math

R = int(8)  # promien planety
N = 5  # liczba planet
G = 2  # stala "grawitacyjna"
L = 1

def compute_dv(p1,p2):
    dx = p2[0]-p1[0]
    dy = p2[1]-p1[1]
    r = math.hypot(dx,dy)
    dx /= r*r
    dy /= r*r
    if(L>1000):
   print "r= ", r, "dx= ", dx, "dy= ", dy, "dx/ r*r = ", dx, "dy/ r*r = ", dy
    L+=1
    return G*dx,G*dy


def rand_color():
    r = 32*random.randint(0,7)
    g = 32*random.randint(0,7)
    b = 22*random.randint(0,7)
    return (r,g,b)


pygame.init()
screen = pygame.display.set_mode((640, 480), 0, 32)

points = []
vs = []
colors = []

for i in range(N):
    points.append( [random.randint(0,639), random.randint(0,480)] )
    vs.append( [0,0] )
    colors.append( rand_color() )

clock = pygame.time.Clock()

screen.fill( (255,255,255))

while True:
    clock.tick(30)

for event in pygame.event.get():
    if event.type == QUIT:
        exit()

for i in range(len(points)):
   for j in range(len(points)):
      if points[i]!=points[j]:
         dvx,dvy = compute_dv( points[i],points[j])
         vs[i][0] += dvx
         vs[i][1] += dvy

for i in range(len(points)):
    points[i][0] += vs[i][0]
    points[i][1] += vs[i][1]

screen.fill( (255,255,255))

for i in range(len(points)):
  L = []
  for w in points[i]:
print int(round(w))
L.append(int(round(w)))
  points[i] = L
  print points[i], "stop"
  #x = raw_input()

  pygame.draw.circle(screen, colors[i], points[i], R)  

pygame.display.update()  
Asked By: lvi

||

Answers:

You are mixing tabs and spaces; don’t do that.

Run your script with python -tt yourscript.py and fix all errors that finds.

Then configure your editor to stick to only spaces for indentation; using 4 spaces per indent is the recommended style by the Python Style Guide.

Next, you are trying to increment the global L here:

def compute_dv(p1,p2):
    # ...

    if(L>1000):
        print "r= ", r, "dx= ", dx, "dy= ", dy, "dx/ r*r = ", dx, "dy/ r*r = ", dy
        L+=1

without declaring it a global. Add global L in that function. Assignment to a name inside a function marks such a name as a local, unless you specifically tell Python it is not.

Answered By: Martijn Pieters

Isn’t a global variable assigned before anything else?

Yes, but that’s completely irrelevant. The compiler sees an assignment within the function and marks the name as being in the local scope. You need to use the global keyword at the beginning of the function to tell the compiler that the name should be in the global scope instead.

def compute_dv(p1,p2):
    global L
     ...

The minimal code to reproduce your bug is

x = 1
def foo():
    x += 1
foo()

This is happening for a number of reasons

  1. First – because in python we have mutable and immutable classes. Ints are immutable, that is when you write x+=1 you actually create another object (which is not true for certain ints due to optimisations CPython does). What actually happens is x = x + 1.
  2. Second – because python compiler checks every assignment made inside a scope and makes every variable assigned inside that scope local to it.
  3. So as you see when you try to increment x compiler has to access a variable that’s local to that scope, but was never assigned a value before.

If you’re using python2 – you only have the option to declare variable global. But this way you would be unable to get a variable from an in-between function like

x = 0
def foo():
  x = 1
  def bar():
    global x
    print x  # prints 0
  bar()
foo()    

In python3 you have nonlocal keyword to address this situation.

Also I would advise you to avoid using globals. Also there is a collection.Counter class that might be useful to you.

Further reading: python docs

Answered By: Kirill Zaitsev
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.