UnboundLocalError:在赋值 Python 之前引用了局部变量“L”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21456739/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 22:53:16  来源:igfitidea点击:

UnboundLocalError: local variable 'L' referenced before assignment Python

pythonpython-2.7

提问by lvi

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()  

采纳答案by Kirill Zaitsev

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+=1you 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 xcompiler has to access a variable that's local to that scope, but was never assigned a value before.
  1. 首先 - 因为在 python 中我们有可变和不可变的类。Ints 是不可变的,也就是说,当您编写时,x+=1您实际上创建了另一个对象(由于 CPython 所做的优化,某些 ints 并非如此)。实际发生的是 x = x + 1。
  2. 其次 - 因为 python 编译器检查在作用域内进行的每个赋值,并使在该作用域内分配的每个变量都成为它的本地变量。
  3. 因此,正如您在尝试递增时所看到的,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 - 您只能选择声明 variable global。但是这样您将无法从中间函数中获取变量,例如

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

In python3 you have nonlocalkeyword to address this situation.

在 python3 中,你有nonlocal关键字来解决这种情况。

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

此外,我建议您避免使用全局变量。还有一个collection.Counter课程可能对您有用。

Further reading: python docs

进一步阅读:python 文档

回答by Martijn Pieters

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

您正在混合制表符和空格;不要那样做。

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

运行您的脚本python -tt yourscript.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 Lhere:

接下来,您尝试在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 Lin that function. Assignment to a name inside a function marks such a name as a local, unless you specifically tell Python it is not.

而不将其声明为全局。添加global L该功能。对函数内的名称赋值会将这样的名称标记为本地名称,除非您明确告诉 Python 不是。

回答by Ignacio Vazquez-Abrams

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 globalkeyword at the beginning of the function to tell the compiler that the name should be in the global scope instead.

是的,但这完全无关紧要。编译器看到函数内的赋值并将名称标记为在本地范围内。您需要global在函数开头使用关键字来告诉编译器该名称应该在全局范围内。

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