Pygame Sprite继承结构调整后出现AttributeError: can't set attribute问题
问题:继承结构调整后出现
AttributeError: can't set attribute 原本代码继承关系为HPBar→ProgressBar→pygame.sprite.Sprite,可正常运行。为扩展组件(按钮、文本框等)新增Widget类,调整为HPBar→ProgressBar→Widget→pygame.sprite.Sprite后,出现上述错误。
HPBar实例化代码
hp_bar = HPBar( x=x, y=y, entity=self.player, groups=[self.camera, self.extras], )
可正常运行的修改前代码
class HPBar(ProgressBar): def __init__(self, entity, *args, **kwargs): max_value = entity.stats["max_hp"] value = entity.stats["hp"] super().__init__( max_value=max_value, value=value, width=32, height=5, *args, **kwargs ) class ProgressBar(pygame.sprite.Sprite): def __init__( self, x: float, y: float, width: int, height: int, groups: List[pygame.sprite.AbstractGroup] = [], max_value: int, value: int, *args, **kwargs ): super().__init__(groups) @property def image(self): _image = # pygame surface 生成逻辑 return _image
修改后出现错误的代码
class ProgressBar(Widget): def __init__( self, max_value: int, value: int, *args, **kwargs ): super().__init__(*args, **kwargs) @property def image(self): _image = # pygame surface 生成逻辑 return _image class Widget(pygame.sprite.Sprite): def __init__( self, x: float, y: float, width: int, height: int, groups: List[pygame.sprite.AbstractGroup] = [], ): super().__init__(groups) self.image = pygame.Surface((width, height))
错误栈信息
File "C:\Users\Hp\Documents\Working\Personal\platformer1\game_models\windows\platformer_window.py", line 127, in load_level hp_bar = HPBar( File "C:\Users\Hp\Documents\Working\Personal\platformer1\game_models\sprites\hp_bar.py", line 16, in __init__ super().__init__( File "C:\Users\Hp\Documents\Working\Personal\platformer1\contrib\models\widgets\progress_bars\progress_bar.py", line 24, in __init__ super().__init__(*args, **kwargs) File "C:\Users\Hp\Documents\Working\Personal\platformer1\contrib\models\widgets\widget.py", line 22, in __init__ self.image = pygame.Surface((width, height)) AttributeError: can't set attribute
调试尝试
在Widget类中打印width和height参数,确认数据类型正确:
super().__init__(groups) print(width, height) print(type(width), type(height)) self.image = pygame.Surface((width, height))
打印结果:
32 5 <class 'int'> <class 'int'>
此外,类似的Player类实现可正常运行:
class Player(pygame.sprite.Sprite): def __init__(self, pos): super().__init__() self.image = pygame.Surface((16, 32))
解决方案
核心原因
ProgressBar类中用@property装饰器定义了image属性,但没有配套的setter方法。当父类Widget的__init__尝试给self.image赋值时,会调用子类ProgressBar的image属性的setter,但子类未定义该方法,导致无法赋值报错。
解决方法1:给ProgressBar的image属性添加setter
class ProgressBar(Widget): def __init__( self, max_value: int, value: int, *args, **kwargs ): super().__init__(*args, **kwargs) @property def image(self): _image = # pygame surface 生成逻辑 return _image @image.setter def image(self, value): # 可根据需求处理赋值逻辑,若无需额外操作可留空 pass
解决方法2:调整Widget的属性命名避免冲突
修改Widget类,将基础surface存储为其他名称,避免和子类的image属性冲突:
class Widget(pygame.sprite.Sprite): def __init__( self, x: float, y: float, width: int, height: int, groups: List[pygame.sprite.AbstractGroup] = [], ): super().__init__(groups) self._base_surface = pygame.Surface((width, height))
后续ProgressBar的image属性可基于self._base_surface进行绘制逻辑处理。
内容的提问来源于stack exchange,提问作者Jobo Fernandez
相关产品推荐
相关产品推荐

