UnboundLocalError: local variable 'L' referenced before Python assignment

when I try 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 first?

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() 
+5
python
Jan 30 '14 at 12:36 on
source share
3 answers

The minimum code to reproduce your error is

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

This happens for a number of reasons.

  • First, because in python we have mutable and immutable classes. Ints are immutable, that is, when you write x+=1 , you are actually creating another object (which is not true for certain ints due to the optimizations that CPython does). Actually, x = x + 1 happens.
  • The second is because the python compiler checks every assignment made inside the scope and makes every variable assigned inside that scope local to it.
  • So, as you can see, when you try to increase x , the compiler must access a variable that is local to this area, but has never been assigned a value before.

If you use python2, you have the option to declare a global variable. But in this way you cannot get a variable from an intermediate function, for example

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

In python3, you have a nonlocal keyword to solve this problem.

I would also advise you to avoid using global variables. There is also a collection.Counter class that might be useful to you.

Further reading: python docs

+19
Jan 30 '14 at 1:07
source share

You mix tabs and spaces; do not do this.

Run the script using python -tt yourscript.py and fix any errors found.

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

Next, you are trying to increase 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 global. Add global L to this function. Assigning a name inside a function marks such a name as local, unless you specifically point out to Python that it is not.

+2
Jan 30 '14 at 12:38
source share

Isn't a global variable assigned first?

Yes, but this is completely inappropriate. The compiler sees the purpose inside the function and marks the name as being in the local area. You need to use the global at the beginning of the function to tell the compiler that the name should be in the global scope.

 def compute_dv(p1,p2): global L ... 
+2
Jan 30 '14 at 12:41
source share



All Articles