在我将其设置为全局时在python中赋值之前引用的局部变量

时间:2014-01-23 16:48:55

标签: python variables global-variables runtime-error

from random import randint
shifts = [4, 4.2, 5, 6, 7]
days_names = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday']
workers_names = ['Itai', 'Or', 'Reut', 'Kuka', 'Aviel']
counter = 1

def shift_arrange(worker):
    for day in days.values():
        counter+=1
        global avilable_shifts
        avilable_shifts = check_avilable_shifts(day)
        if not random_shifte_selector(worker,day): soft_reset(worker)

我将counter设置为全局变量,当我尝试运行此代码时,我得到局部变量错误:

Traceback (most recent call last):
  File "C:\Or\mypy\shift creator\shift cretor.py", line 144, in <module>
    for w in workers.values(): shift_arrange(w)
  File "C:\Or\mypy\shift creator\shift cretor.py", line 105, in shift_arrange
    counter+=1
UnboundLocalError: local variable 'counter' referenced before assignmen

我看到有人在这里问这个问题,他删除了他的pyc文件或其他东西(我不知道它是什么),它的工作正常。为什么会这样?它不会发生在程序中的其他变量中。

谢谢,或者

2 个答案:

答案 0 :(得分:4)

您需要声明一个全局变量

def shift_arrange(worker):
    global counter
    for day in days.values():
        counter+=1
        ...

由于您修改了该范围内的counter,因此python会将其视为局部变量,除非您将其声明为global。如果您只需要阅读它,那就没有必要了。

请考虑以下事项:

这有效:

c = 0
def f():
   print c
f()

虽然这不是:

c = 0 
def f():
  print c
  c = 1
f()

虽然这样做:

c = 0
def f():
  global c
  print c
  c = 1
f()
print c  # prints 1, f() modified the global value

答案 1 :(得分:1)

这里有很多要查找的内容,但一般来说python都有名称和分配给它们的东西。该名称可以是本地或全球范围。

对于读取,python查看本地范围,然后查看全局范围,并使用它找到的第一个(如果没有,则使用错误)。

对于写入... python需要知道放在哪里。通常情况下,它会查看本地范围,如果不存在,则在那里创建一个变量并赋值。这将隐藏全局变量。你可以让它看看全局并使用它,如果它存在 - 但这可能是不可取的&amp;意外。所以,你需要一种方法告诉python使用全局变量,如果它存在(然后,如果它不存在,它将创建)。

这有时会导致一些奇怪的行为。除了早先的回答......

c = 0

# Passes. We are just looking up the global variable.
def f1(x):
    return x + c

# Passes, but may not be as expected. Sets a local variable c to a value, does not 
# modify the global one.
def f2(x):
    c = x

# Correct way to do the above; now it sets the global variable.
def f3(x):
    global c
    c = x

# What if you mix them?
def f4(x):
    c = c + x
# This fails. What happens is that first it sees that it's writing to c, and it's
# not marked global, so it assigns c to the local space. Then it tries to dereference
# it. Since we've marked it local, it masks the global one, and since it doesn't
# have a value, it throws an error. c += x works the same way and also fails.

# However, this works, though is just as equally wrong:
def f5(x):
    d = c
    c = d + x
# This one works, because we copy the value of the global c into the local d.
# Then, the second line assigns a local c to addition of local d and x. 
# But does not update the global.

# Each line is separate though:
def f6(x):
    d = c
    c = c + 1
# You might think that d=c already made c local for the whole function. But it doesn't
# work like that. The first line just looks up the value for c, which it finds
# globally, but then forgets about it - it cares about the object c is the name of,
# not the name c itself. The second line still fails.