继承Pygame Vector2的自定义类无法创建以x/y开头的属性,求原因与解决方法
继承Pygame Vector2的自定义类无法创建以x/y开头的属性,求原因与解决方法
这个问题我之前也踩过坑,其实是Pygame的Vector2类内部做了特殊的属性拦截逻辑导致的。
原因分析
pygame.Vector2为了实现x、y坐标的便捷读写,重写了__getattr__和__setattr__这两个特殊方法。当你尝试给实例设置以x或y开头的属性时,它会错误地将其判定为坐标相关的操作,触发内部的序列校验逻辑——而你传入的是True这种非序列值,自然就抛出了TypeError: a sequence is expected错误。
打个比方:你写self.xattribute = attribute时,Vector2的属性拦截逻辑会把xattribute当成和x坐标相关的操作,试图按序列规则去处理它,但你的值不符合要求,所以报错。而像attributex这种x在末尾的属性名,不会触发这个特殊拦截,因此能正常赋值。
解决方法
这里有两个实用的方案可以解决这个问题:
方案1:直接操作实例的__dict__
绕过Vector2的__setattr__拦截,直接把属性写入实例的私有字典:
class CustomVector(pygame.Vector2): def __init__(self, vector, attribute): super().__init__(vector) self.__dict__['xattribute'] = attribute # 直接通过字典赋值,避开拦截 CustomVector((0,0), True)
方案2:重写__setattr__方法
在自定义类里重写__setattr__,先判断属性是否为自定义属性,是则自行处理,否则交给父类:
class CustomVector(pygame.Vector2): def __init__(self, vector, attribute): super().__init__(vector) self.xattribute = attribute def __setattr__(self, name, value): # 可以把所有自定义属性放在列表里统一判断 custom_attrs = ['xattribute'] if name in custom_attrs: self.__dict__[name] = value else: # 非自定义属性交给父类的逻辑处理 super().__setattr__(name, value) CustomVector((0,0), True)
这样就能避开Vector2的特殊属性处理逻辑,正常创建以x/y开头的自定义属性了。
备注:内容来源于stack exchange,提问作者Capocho
相关产品推荐
相关产品推荐

