Tkinter全局变量报错UnboundLocalError:userScore/comScore赋值前引用
错误根因
你遇到的报错是Python变量作用域规则的典型问题:
- 仅在函数内部读取全局变量时,不需要额外声明
- 但如果要修改全局变量的绑定(
userScore += 1本质是重新赋值操作),必须在函数开头显式用global关键字声明要操作的是全局变量,否则Python会把变量识别为未初始化的局部变量,就会抛出你遇到的UnboundLocalError。
你之前尝试用全局变量没成功,大概率是漏了在play函数开头加global声明。而传参方案会重置分数的原因也很明确:你每次传的是全局变量的当前值,函数内部修改的只是局部参数,不会同步到全局变量,下次调用传的还是初始值,自然分数每次都会重置。
修复方案
只需要在play函数开头加上全局变量声明即可,修改后的代码如下:
userScore = 0 comScore = 0 options = [[comRock, 'Rock'], [comPaper, 'Paper'], [comScissors, 'Scissors']] # def start(): # startFrame.pack_forget() # visualFrame.pack() # controlFrame.pack() def play(img, userIn): # 新增这行,显式声明要修改的是全局变量 global userScore, comScore comIn = random.choice(options) Label(visualFrame, image=img, borderwidth=0, highlightthickness=0).grid(row=0, column=0) Label(visualFrame, image=comIn[0], borderwidth=0, highlightthickness=0).grid(row=0, column=2) Label(visualFrame, image=vsImg, borderwidth=0, highlightthickness=0).grid(row=0, column=1) if userIn == comIn[1]: Label(visualFrame, image=tieImg, borderwidth=0, highlightthickness=0).grid(row=0, column=0, columnspan=3) elif (userIn == "Rock" and comIn[1] == "Scissors") or (userIn == "Scissors" and comIn[1] == "Paper") \ or (userIn == "Paper" and comIn[1] == "Rock"): Label(visualFrame, image=wonImg, borderwidth=0, highlightthickness=0).grid(row=0, column=0, columnspan=3) userScore += 1 else: Label(visualFrame, image=lostImg, borderwidth=0, highlightthickness=0).grid(row=0, column=0, columnspan=3) comScore += 1 Label(visualFrame, text=str(userScore) + ':' + str(comScore)).place(x=295, y=205)
可选优化(避免使用全局变量)
如果不想用全局变量(全局变量过多不利于代码维护),可以把分数封装为可变对象,比如长度为1的列表:
# 初始化时改为列表 userScore = [0] comScore = [0] # 函数内部修改时操作列表元素,不需要声明global userScore[0] += 1 comScore[0] += 1
列表是可变对象,函数内部可以直接修改其内部元素,不会触发作用域判定问题,也能避免传参重置的问题。
内容的提问来源于stack exchange,提问作者ronanoch
相关产品推荐
相关产品推荐

