Python代码yield返回列表变元组,Tkinter游戏playerpos报错原因求解
playerpos报元组不可修改的核心原因
- 你的
moverect方法中playerpos[0],playerpos[2] += x写法存在语法问题:Python会自动将逗号分隔的多个左值封装为元组处理,该行代码等价于(playerpos[0], playerpos[2]) = (playerpos[0], playerpos[2]) + x,运算过程中涉及元组操作,自然会抛出元组不可修改的报错,和你原本playerpos是不是列表没有关系。 - 全局变量滥用加剧了问题排查难度:你将playerpos设为全局变量,却没有在
moverect方法中声明global playerpos,如果代码其他位置存在同名局部变量赋值,会进一步导致变量类型被意外篡改。该场景下playerpos属于player实例的专属属性,完全不需要设为全局变量。 - __init__中初始化playerpos的逻辑冗余且存在隐患:你先将四个坐标转字符串拼接再拆分转int的逻辑,只要坐标值大于9就会生成超过4个元素的列表,虽然你后续用
playerpos = [sx1,sy1,sx2,sy2]覆盖了该结果,但属于完全无用的冗余代码。
yield返回列表变元组的原因
你贴出的代码中没有包含yield相关逻辑,该问题属于Python的默认语法规则:只要你用逗号分隔多个值返回/产出,Python会自动将其封装为元组。比如yield x, y会返回元组,只有显式用方括号包裹yield [x, y]才会返回列表。
修复参考代码
from tkinter import Tk, Button, Canvas, messagebox, mainloop import tkinter.ttk from tkinter.font import * from math import * tk = Tk() c = Canvas(tk,width=1920,height=950,bg="#000000") c.pack() fallspeed = 0 gravity = 0.2 class Player: def __init__(self, sx1, sy1, sx2, sy2): # 改为实例属性,避免全局变量污染 self.playerpos = [sx1, sy1, sx2, sy2] self.sx1 = sx1 self.sx2 = sx2 self.sy1 = sy1 self.sy2 = sy2 self.rect = c.create_rectangle(sx1, sy1, sx2, sy2, fill="#14eeee") def moverect(self, x, y): c.move(self.rect, x, y) # 分开赋值,避免多值增量赋值的语法问题 self.playerpos[0] += x self.playerpos[2] += x self.playerpos[1] += y self.playerpos[3] += y def pickup(self, item): pass
内容的提问来源于stack exchange,提问作者user14354511
相关产品推荐
相关产品推荐

