如何通过 while/for 循环创建 class 的许多精确实例(以访问它们的属性)?

How do I create many precise instances of a class (to access their attributes) through a while/for loop?

我正在尝试使用 pygame 制作一个 atari 闯关风格的游戏,并且我希望可破碎的方块是具有某些属性的对象,我可以随着游戏的进行而更改这些属性。 因此,我创建了一个 "Block" class 和一个后续函数,该函数多次循环遍历此 class 将实例分配给列表。 我遇到的问题是我没有为每个对象设置不同的 "name",因此很难访问它们的各个属性。

这是一个例子:

class Block:
    def __init__(self):
        self.brick = pygame.sprite.Sprite()
        pygame.sprite.Sprite.__init__(self.brick)
        self.brick.image = pygame.Surface([width, height])
        self.brick.image.fill(RED)
        self.brick.rect = self.brick.image.get_rect()
    def blockType (self, hardness):
        self.hardness = hardness  

def lay ():
    layoutm = []
    for x in range (0, 5):
        layoutl = []
        for y in range (0, 12):
            layoutl.append (Block())
        layoutm.append (layoutl)
    return layoutm  

layoutm=lay()

horIndex = -1
for x in range(20, 195, 35):
    horIndex += 1
    verIndex = -1
    for y in range (20, 660, 55):
        verIndex += 1
        #set_trace ()
        brick = (layoutm[horIndex][verIndex]).brick
        brick.rect.topleft = (y,x)
        block_list.add(brick)
        list_of_sprites.add(brick)

你们中的一些人可能会指出,我可以简单地从 pygame.sprite.Sprite() 父 class 继承,这可能是一个解决方案(属性太多或其他可能),但由于某些原因,这不是为我工作。

layoutm=lay() 之后的所有内容都是各个块的位置代码,我包含它的唯一原因是展示我打算如何访问每个相应 self.brick 的位置属性。可能不是最好的方法,但是构造函数之后的所有方法对于我打算添加到游戏中的功能都是必需的(这就是为什么我留在 blockType () 中以简化问题)。

我的问题基本上是,如果我总是必须使用 set_trace() 之后的代码(这是 运行 调试器 pudb 的命令) 来访问这些单独的实例。

仅供参考:我浏览所有这些东西的原因是因为我计划有一些列表,例如

level_1 = [  
[1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1]] 

level_2 = [
[0,1,1,2,2,3,3,2,2,1,1,0],
[1,1,2,2,3,3,3,3,2,2,1,1],
[1,2,2,3,3,4,4,3,3,2,2,1],
[1,1,2,2,3,3,3,3,2,2,1,1],
[0,1,1,2,2,3,3,2,2,1,1,0]]

代表关卡布局,说明块的类型(代码将被修改当然可以工作。

此外,我的术语有时可能是错误的(我用的是法语 class),例如混淆实例与对象(我称它们相同,但它们可能不同)所以请随时提问如果有什么不明白的,我。

您的示例似乎有很多内容,所以我将向您展示我将如何组织它。我对 PyGame 没有什么经验,所以我会把你的 Brick class 的技巧留给其他人,但我会尽力帮助你存储 Brick。

这就是我定义的方式 lay:

def lay():
    return [[Brick() for y in range(12)] for x in range(5)]
layoutm = lay()

这个构造称为list comprehension。它比使用 "for" 和 "append" 更快,而且我认为它看起来更清晰。它将创建一个包含 5 个列表的列表,这些列表将代表行。每行将包含 12 块积木。

现在要处理创建砖块后对其属性的编辑:

for (row, y) in zip(layoutm, range(20, 195, 35)):
    for (brick, x) in zip(row, range(20, 660, 55)):
        brickSprite = brick.brick
        brickSprite.rect.topleft = (y, x)

这个有点复杂。首先,Python 允许你迭代任何可迭代对象中的对象,像这样:

for num in [0, 1, 2]:
    print(num)

这将打印出值 0、1 和 2。现在,zip 是一个接受两个可迭代对象的函数,而 returns 是一个包含对象对的可迭代对象。例如:

for num_name in zip([0, 1, 2], ["zero", "one", "two"]:
    print(num_name)

这将打印值 (0, "zero")、(1, "one") 和 (2, "two")。现在回到我的代码片段:首先,外循环将遍历每一行及其 y 坐标。然后,内部循环将遍历该行中的每个砖块及其 x 坐标。之后我们就可以对砖块进行操作了

请注意,我没有在 for 循环中构建 block_list 和 list_of_sprites。我会用另一个 list comprehension:

block_list      = [brick       for row in layoutm for brick in row]
list_of_sprites = [brick.brick for brick in block_list]

block_list 现在应该包含 layoutm 列表中的每个 Brick,并且 list_of_sprites 应该包含与每个 Brick 对应的 Sprites。如果您决定让 Brick subclass 成为 Sprite class,那么您可以相应地更改它。