Tile类tile_pref["sprites"]长度异常及循环append调用问题修复咨询
咱们先直接戳破问题的核心:你定义的tile_pref是类变量,不是实例变量,这才是导致sprites列表长度疯长的根本原因,和img.get_region()返回引用完全没关系。
为什么每次循环都会触发append?
在Python中,直接写在类体里的变量(比如你这里的tile_pref = { "sprites": [] })属于类属性,所有该类的实例都会共享同一个引用。也就是说,不管你创建多少个Tile对象,它们操作的都是同一个tile_pref字典里的sprites列表。
你在__init__里写的self.tile_pref["sprites"].append(img),其实是在访问类级别的tile_pref(因为实例本身没有自己的tile_pref属性,Python会自动向上查找类的属性)。所以每生成一个Tile实例,就会往同一个列表里加一张图,最终长度自然等于Tile的总数。
至于你猜测的img.get_region()返回引用的问题:其实pyglet的get_region()返回的是独立的TextureRegion对象,每个区域都是独立的,不会互相影响,这个猜测方向错啦。
修复方案
把tile_pref改成实例变量,让每个Tile实例拥有自己独立的字典和sprites列表,直接在__init__里初始化就好:
class Tile: def __init__(self, img, pos): # 每个实例单独初始化tile_pref,sprites初始就包含传入的img self.tile_pref = { "sprites": [img] } self.pos = pos def img(self, x, y, tilemap, t): return self.tile_pref["sprites"][0]
另外补充一点:你原来的pos = Vector2(vector_zero)也是类变量,虽然在__init__里给self.pos赋值会覆盖掉,但为了代码清晰,最好不要在类里定义这种实例级别的默认值,直接在__init__里处理就好,就像上面的代码那样。
验证效果
修改后,每个Tile实例的tile_pref["sprites"]列表初始长度就是1,完全符合你的预期,不会再随着实例数量增长了。
内容的提问来源于stack exchange,提问作者ISD

