You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环修改Cube对象Face属性异常:双方面属性同步问题咨询

问题:Face对象属性更新后出现同步问题

我将「Cube」对象定义为包含6个「Face」对象(正方形)的列表(实现旋转功能前先只用2个),代码如下:

class Face():
    def __init__(self, center, anglex = 0, angley = 0, color = (255,255,255),):
        self.center = center
        self.anglex = anglex
        self.angley = angley
        self.color = color

    def setAngle(self, anglex, angley):
        self.anglex = anglex
        self.angley = angley
        
    def setCenter(self, cx, cy):
        self.center[0] = cx
        self.center[1] = cy

class Cube():
    def __init__(self, center):
        self.center = center
        
        face1 = Face(center, 0, 0, (255,0,0))
        face6 = Face(center, 180, 0, (0))
        
        #self.faces = [face1, face2, face3, face4, face5, face6]
        self.faces = [face1, face6]

height = 900
width = 1500
screen = pygame.display.set_mode([width, height])

cube = Cube([width/2, height/2])

当我尝试修改Face的中心和角度实现旋转效果时,属性无法正确更新,最终两个Face的角度/中心完全相同。

比如这段代码,循环内打印每个Face的center[0]时,结果是正确的:

for face in cube.faces:
        ax = (face.anglex + varx)%360
        face.setAngle(ax, face.angley)
        
        cx = width/2 + math.sin(math.radians(face.anglex))*50
        face.setCenter(cx, face.center[1])
        
        print(face.center[0])

但如果把打印放到循环外,两个Face的center[0]就完全一样了:

for face in cube.faces:
        ax = (face.anglex + varx)%360
        face.setAngle(ax, face.angley)
        
        cx = width/2 + math.sin(math.radians(face.anglex))*50
        face.setCenter(cx, face.center[1])
        
for face in cube.faces:
        print(face.center[0])

我猜测是对类对象属性的工作机制理解有问题,求解释原因?


解答

核心问题是所有Face对象共享了同一个center列表引用。

列表是Python中的可变对象,当你在Cube的__init__方法里,把同一个center列表传给face1和face6时,这两个Face对象的self.center实际上指向内存中同一个列表。后续调用setCenter修改center[0]时,都是在修改这个共享的列表。

循环内打印看起来正确,是因为循环过程中:

  1. 第一次处理face1时,修改了共享列表的值,此时打印的是这个修改后的值
  2. 第二次处理face6时,又修改了同一个共享列表的值,打印的是这次修改后的结果

但循环结束后,两个Face的center属性依然指向同一个列表,所以最后一次修改的结果会覆盖之前的,导致两者的center完全相同。

修复方案

方案1:在Face类内部创建列表副本

修改Face的__init__方法,对传入的center创建副本,避免共享引用:

class Face():
    def __init__(self, center, anglex = 0, angley = 0, color = (255,255,255),):
        self.center = center.copy()  # 或者用 list(center) 创建副本
        self.anglex = anglex
        self.angley = angley
        self.color = color

方案2:创建Face对象时传入副本

在Cube的__init__里,给每个Face传入center的副本:

face1 = Face(center.copy(), 0, 0, (255,0,0))
face6 = Face(center.copy(), 180, 0, (0))

两种方案都能让每个Face拥有独立的center列表,修改时就不会互相影响了。


内容的提问来源于stack exchange,提问作者marcoG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 19:54:28