为什么有些Python变量可以保持全局性,而有些需要定义为全局变量?

5

我有点不理解为什么有些变量是局部的,有些是全局的。例如,当我尝试这样做:

from random import randint

score = 0

choice_index_map = {"a": 0, "b": 1, "c": 2, "d": 3}

questions = [
    "What is the answer for this sample question?",
    "Answers where 1 is a, 2 is b, etc.",
    "Another sample question; answer is d."
]

choices = [
    ["a) choice 1", "b) choice 2", "c) choice 3", "d) choice 4"],
    ["a) choice 1", "b) choice 2", "c) choice 3", "d) choice 4"],
    ["a) choice 1", "b) choice 2", "c) choice 3", "d) choice 4"]
]

answers = [
    "a",
    "b",
    "d"
]

assert len(questions) == len(choices), "You haven't properly set up your question-choices."
assert len(questions) == len(answers), "You haven't properly set up your question-answers."

def askQ():
    # global score
    # while score < 3:
        question = randint(0, len(questions) - 1)

        print questions[question]
        for i in xrange(0, 4):
            print choices[question][i]
        response = raw_input("> ")

        if response == answers[question]:
            score += 1
            print "That's correct, the answer is %s." % choices[question][choice_index_map[response]]
            # e.g. choices[1][2]
        else:
            score -= 1
            print "No, I'm sorry -- the answer is %s." % choices[question][choice_index_map[answers[question]]]
        print score

askQ()

I get this error:

Macintosh-346:gameAttempt Prasanna$ python qex.py 
Answers where 1 is a, 2 is b, etc.
a) choice 1
b) choice 2
c) choice 3
d) choice 4
> b
Traceback (most recent call last):
  File "qex.py", line 47, in <module>
    askQ()
  File "qex.py", line 39, in askQ
    score += 1
UnboundLocalError: local variable 'score' referenced before assignment

现在,我完全明白为什么它在分数上给我抛出一个错误。我没有在全局范围内设置它(我故意注释掉那部分来展示这一点)。而我特意不使用while子句让它继续执行(否则它甚至不会进入子句)。令人困惑的是为什么它不给我questions,choices和answers相同的错误提示。当我取消注释这两行时,脚本完美地工作了--即使我没有将问题、答案和选项定义为全局变量。为什么会这样呢?这是我从搜索其他问题中没有能够发现的一个问题--在这里,Python似乎表现得不一致。这是否与我使用列表作为其他变量有关?为什么呢?
(此外,第一次发布者;非常感谢所有提供帮助的人。)

2
在方法中进行赋值操作总是会创建一个[新的]本地绑定,除非该变量被声明为global:赋值操作不会使变量“非全局”,而是用新的绑定覆盖了全局变量。 - user166390
3个回答

5

这是因为你正在将值分配给score变量。questionsanswers变量只被读取,没有被写入。

当你将值分配给变量时,该变量的作用域限定在当前方法、类等范围内。当你尝试获取变量的值时,它会首先在当前范围内查找,然后在外部范围中查找,直到找到匹配项。


太好了。感谢回复!完全有道理。 - pswaminathan

2
这句话的意思是:如果你认为全局是一个解析器指令,那么这就完全有意义。当你在执行某个操作时...(后面的文本没有提供上下文,无法翻译完整意思)
score += 1 

"

" 被翻译为 "

"。
score = score + 1

当解析器到达“score =”时,它会导致解释器不在本地空间之外搜索。

http://docs.python.org/2/reference/simple_stmts.html#global


这是有道理的。我原本认为当一个变量在比我使用它的块更高的地方定义时,所有对该变量的操作都适用于其作用域。不过感谢您提供的链接,这有助于我理解赋值和读取遵循不同的过程。 - pswaminathan

1

发生的情况是,Python 会先在局部作用域中查找变量,然后再查找全局作用域。因此,当涉及到 questionsanswers 时,它们从未在局部作用域中设置,因此 Python 转而查找全局作用域,在那里找到了它们。但对于 score,Python 看到你进行了赋值操作(score += 1score -= 1),并锁定了局部作用域。但是当你在这些语句中提到 score 时,它还不存在,因此 Python 抛出异常。


太好了,感谢回复!完全有道理。 - pswaminathan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接