Python-使用全局。不能在python打字游戏中使用nonlocal

时间:2017-05-01 13:25:16

标签: python

这是我的代码:

enter code here
def Game():
try:

    tkMessageBox.showinfo("Hello!", "Welcome To my Game, %name")
    root.destroy()

    colors = ['Red', 'Blue', 'Green', 'Pink', 'Orange', 'Black', 'Yellow', 
    'White', 'Purple', 'Brown']
    score = 0
    timeLeft = 30

    def startGame(event):
        global timeLeft
        if timeLeft == 30:
            countdown()

        nextColor()

    def nextColor():
        global score
        global timeLeft

        if timeLeft > 0:
            e.focus_set()
            if e.get().lower() == colors[1].lower():
                score += 1

        e.delete(0, Tkinter.END)
        random.shuffle(colors)
        label.config(fg=str(colors[1]), text=str(colors[0]))
        scoreLabel.config(text="Score: " + str(score))

    def countdown():
        global timeLeft

        if timeLeft > 0:
            timeLeft -= 1
            time.config(text="Time Left: " + str(timeLeft))
            time.after(1000, countdown)

这是我得到的错误

C:\Python27\python.exe D:/pythonaldecoa/TypingGameColor.py
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1542, in __call__
    return self.func(*args)
  File "D:/pythonaldecoa/TypingGameColor.py", line 17, in startGame
    if timeLeft == 30:
NameError: global name 'timeLeft' is not defined

看到带缩进的程序后,事情就更清楚了: 'timeleft'和'score'不是全局的,它们是函数'Game()'的本地。 要在嵌套函数中使用它们,nextColor()和countdown()要求声明为非本地,而不是全局。

1 个答案:

答案 0 :(得分:2)

您没有明确提出问题,但我似乎使用了错误的关键字。是的,这些变量是非本地的,但是您使用global关键字来定义它们,而是使用nonlocal关键字,而python似乎并未在全局范围内看到这些变量,因此使用global是无用的。 nonlocal rules documented here

例如,更改此内容:

def Game():
    ...
    score ...
    timeleft ...
    ...
    def nextColor():
        global score
        global timeLeft

        if timeLeft > 0:
            e.focus_set()
            if e.get().lower() == colors[1].lower():
                score += 1

到此:

def Game():
    ...
    score ...
    timeleft ...
    ...
    def nextColor():
        nonlocal score
        nonlocal timeLeft

        if timeLeft > 0:
            e.focus_set()
            if e.get().lower() == colors[1].lower():
                score += 1

此解决方案在2.7中不起作用。如果不需要,则不应使用2.7,但如果这是用于作业或遗留代码库,则可以通过解决方案discussed here来解决2.7的限制:

def outer():
    d = {'y' : 0}
    def inner():
        d['y'] += 1
        return d['y']
    return inner

f = outer()
print(f(), f(), f()) #prints 1 2 3

这是有效的,因为你可以读取非局部变量,但是你不能改变它们,所以你需要某种可变容器,因此需要字典。

在您的情况下,这可能如下所示:

def Game():
    ...
    game_stats['score'] ...
    game_stats['timeLeft'] ...
    ...
    def nextColor():

        if game_stats['timeLeft'] > 0:
            e.focus_set()
            if e.get().lower() == colors[1].lower():
                game_stats['score'] += 1