This question already has an answer here:
这个问题已经有了答案:
- UnboundLocalError in Python [duplicate] 8 answers
- Python中的UnboundLocalError[复制]8答案。
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
我的Python版本是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()
3 个解决方案
#1
19
The minimal code to reproduce your bug is
复制bug的最小代码是。
x = 1
def foo():
x += 1
foo()
This is happening 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 actually create another object (which is not true for certain ints due to optimisations CPython does). What actually happens is x = x + 1. - 首先,因为在python中,我们有可变和不可变的类。Ints是不可变的,即当您编写x+=1时,您实际上会创建另一个对象(这对于某些Ints来说是不正确的,因为optimisations CPython是这样做的)。实际发生的是x = x + 1。
- Second - because python compiler checks every assignment made inside a scope and makes every variable assigned inside that scope local to it.
- 第二,因为python编译器检查了一个范围内的每一个赋值,并使每个赋值在这个范围内。
- 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. - 当你试图增加x编译器时,你会看到一个变量在这个范围内是局部的,但以前从未赋值过。
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
如果您使用的是python2,那么您只能选择声明变量全局变量。但是这样你就无法从中间的函数中得到一个变量。
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.
在python3中,您有非本地关键字来处理这种情况。
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
进一步阅读:python文档
#2
2
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
...
#3
2
You are mixing tabs and spaces; don't do that.
你在混合制表符和空格;不要这样做。
Run your script with python -tt yourscript.py
and fix all errors that finds.
用python -tt脚本运行脚本。py并修复所有发现的错误。
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.
然后配置您的编辑器只保留缩进的空间;每个缩进使用4个空格是Python风格指南推荐的风格。
Next, you are trying to increment the global L
here:
接下来,你要增加全局L:
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.
没有声明它是全球性的。在这个函数中添加全局L。在函数内的名称赋值标志着一个本地的名称,除非你明确地告诉Python它不是。
#1
19
The minimal code to reproduce your bug is
复制bug的最小代码是。
x = 1
def foo():
x += 1
foo()
This is happening 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 actually create another object (which is not true for certain ints due to optimisations CPython does). What actually happens is x = x + 1. - 首先,因为在python中,我们有可变和不可变的类。Ints是不可变的,即当您编写x+=1时,您实际上会创建另一个对象(这对于某些Ints来说是不正确的,因为optimisations CPython是这样做的)。实际发生的是x = x + 1。
- Second - because python compiler checks every assignment made inside a scope and makes every variable assigned inside that scope local to it.
- 第二,因为python编译器检查了一个范围内的每一个赋值,并使每个赋值在这个范围内。
- 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. - 当你试图增加x编译器时,你会看到一个变量在这个范围内是局部的,但以前从未赋值过。
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
如果您使用的是python2,那么您只能选择声明变量全局变量。但是这样你就无法从中间的函数中得到一个变量。
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.
在python3中,您有非本地关键字来处理这种情况。
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
进一步阅读:python文档
#2
2
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
...
#3
2
You are mixing tabs and spaces; don't do that.
你在混合制表符和空格;不要这样做。
Run your script with python -tt yourscript.py
and fix all errors that finds.
用python -tt脚本运行脚本。py并修复所有发现的错误。
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.
然后配置您的编辑器只保留缩进的空间;每个缩进使用4个空格是Python风格指南推荐的风格。
Next, you are trying to increment the global L
here:
接下来,你要增加全局L:
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.
没有声明它是全球性的。在这个函数中添加全局L。在函数内的名称赋值标志着一个本地的名称,除非你明确地告诉Python它不是。