Python中创建Paddle类第二个实例时第一个实例消失问题
Pong游戏左侧Paddle消失问题排查与修复
问题现象
使用Python Turtle模块开发Pong游戏,创建left_pad = Paddle("left")和right_pad = Paddle("right")实例后,左侧Paddle短暂显示后消失,仅右侧Paddle正常保留在屏幕上,形状与定位均符合预期。
问题代码
paddles.py
from turtle import Turtle class Paddle: side = "" paddle = [Turtle(shape="square") for i in range(4)] paddle_bottom = -30 paddle_range = [] def __init__(self, side): self.side = side self.paddle_range = [self.paddle[0].screen.canvheight-10, -self.paddle[0].screen.canvheight+10] for box in range(len(self.paddle)): self.paddle[box].penup() # Set to middle height for box in range(len(self.paddle)): self.paddle[box].sety(self.paddle_bottom + 20*box) # Set to sides if side == "left": for box in range(len(self.paddle)): self.paddle[box].setx((-self.paddle[0].screen.canvwidth / 2) + 20) else: for box in range(len(self.paddle)): self.paddle[box].setx((self.paddle[0].screen.canvwidth / 2) - 20) def move(): global paddle for box in len(range(paddle)): paddle[box].forward(1) paddle[0].screen.update() def move_up(): global paddle_range global move for box in len(range(paddle)): paddle[box].setheading(90) while paddle[-1].ycor() < paddle_range[0]: move() def move_down(): for box in len(range(paddle)): paddle[box].setheading(270) while paddle[0].ycor() > paddle_range[1]: move() if side == "left": paddle[0].screen.onkey(key="w", fun=move_up) paddle[0].screen.onkey(key="s", fun=move_down) else: paddle[0].screen.onkey(key="Up", fun=move_up) paddle[0].screen.onkey(key="Down", fun=move_down)
game.py
from turtle import Screen from paddles import Paddle screen = Screen() screen.bgcolor("beige") screen.title("Pong!") screen.setup(width=820, height=620) screen.screensize(canvwidth=800, canvheight=600) screen.tracer(0) screen.listen() left_pad = Paddle("left") screen.update() right_pad = Paddle("right") screen.update() screen.exitonclick()
问题根源
- 类属性共享冲突:
paddle是Paddle类的类属性,所有实例共享同一个Turtle列表。创建右侧Paddle时,会覆盖左侧Paddle中所有Turtle的位置,导致左侧Paddle被移至右侧。 - 类级事件绑定错误:类定义末尾的事件绑定代码在类加载时执行,而非实例化阶段,此时
side为空字符串,绑定逻辑完全失效。 - 方法定义不规范:
move、move_up、move_down缺少self参数,错误使用全局变量,无法正确访问实例属性。 - 循环语法错误:
for box in len(range(paddle))是语法错误,正确写法应为for box in range(len(paddle))。 - 阻塞事件循环:
move_up和move_down中的while循环会阻塞Turtle的事件循环,导致程序无响应。
修复后的代码
paddles.py
from turtle import Turtle class Paddle: def __init__(self, side, screen): self.side = side self.screen = screen # 每个实例独立拥有Turtle列表,避免共享冲突 self.paddle = [Turtle(shape="square") for _ in range(4)] self.paddle_bottom = -30 self.paddle_range = [self.screen.canvheight - 10, -self.screen.canvheight + 10] for box in self.paddle: box.penup() box.color("black") # 设置初始高度 for idx, box in enumerate(self.paddle): box.sety(self.paddle_bottom + 20 * idx) # 设置左右位置并绑定按键 if side == "left": x_pos = (-self.screen.canvwidth / 2) + 20 self.screen.onkey(key="w", fun=self.move_up) self.screen.onkey(key="s", fun=self.move_down) else: x_pos = (self.screen.canvwidth / 2) - 20 self.screen.onkey(key="Up", fun=self.move_up) self.screen.onkey(key="Down", fun=self.move_down) for box in self.paddle: box.setx(x_pos) def move(self, direction): # 单次移动逻辑,避免阻塞事件循环 for box in self.paddle: box.setheading(direction) box.forward(20) self.screen.update() def move_up(self): # 边界检查后再移动 if self.paddle[-1].ycor() < self.paddle_range[0]: self.move(90) def move_down(self): # 边界检查后再移动 if self.paddle[0].ycor() > self.paddle_range[1]: self.move(270)
game.py
from turtle import Screen from paddles import Paddle screen = Screen() screen.bgcolor("beige") screen.title("Pong!") screen.setup(width=820, height=620) screen.screensize(canvwidth=800, canvheight=600) screen.tracer(0) screen.listen() # 创建实例时传入screen对象,方便内部访问 left_pad = Paddle("left", screen) right_pad = Paddle("right", screen) screen.update() screen.exitonclick()
修复说明
- 将
paddle从类属性改为实例属性,确保每个Paddle实例拥有独立的Turtle对象集合。 - 将事件绑定逻辑移至
__init__方法内,根据实例的side参数绑定对应按键。 - 为所有实例方法添加
self参数,通过self访问实例属性,移除错误的全局变量引用。 - 修复循环语法错误,使用
enumerate简化索引遍历逻辑。 - 移除
while循环,改为单次移动的逻辑,避免阻塞Turtle事件循环,保证程序响应性。 - 创建Paddle实例时传入
screen对象,方便实例内部访问屏幕属性与绑定事件。
内容的提问来源于stack exchange,提问作者Aya Noaman
相关产品推荐
相关产品推荐

