可以在Python中给导入的类添加属性吗?

3 投票
1 回答
2567 浏览
提问于 2025-04-18 10:44

我来解释一下我的情况,这样我的问题就更容易理解了。

我正在用Python和Pygame编写一个游戏。这个游戏非常简单,没有太多的图形,我希望每个关卡都是由黑色和白色方块组成的网格。我觉得用一串1和0来定义每个关卡会更合理,比如这样:

0000
0101
1010
1111

而不是:

level1 = (pygame.Rect(0, 0, 100, 100), pygame.Rect(100, 0, 100, 100),
pygame.rect(200, 0, 100, 100), pygame.rect(300, 0, 100, 100),
...
...

这样做会显得很笨重,也很麻烦,会让设计关卡变得非常困难。而且在Python中,代码的可读性很重要,优雅的代码总是比丑陋的代码要好。=)

我打算使用第一种方法,创建一个函数,返回一个pygame.Rect对象的列表(类似于上面的代码),其中0代表黑色方块,1代表白色方块。不过,遗憾的是,pygame.Rect对象并不包含关于它们颜色的任何信息。

现在我的问题有两个方面。

1) 有没有办法给一个已经存在的类添加一个属性(在这个例子中,就是给rect添加color属性),而不需要去修改它的源代码?(因为那样做似乎真的很糟糕。)

2) 如果可以这样做,是否明智?还是说这样做只是在自找麻烦?

当然,我知道这不是实现我想要的唯一方法。如果我想用一种比较传统的方法,我会像这样创建一个类:

class tile:
    def __init__(self, x, y, width, height, color):
        self.rect = pygame.Rect(x, y, width, height)
        self.color = color

    def draw(self):
        pygame.draw.rect(displaysurface, self.color, self.rect)

这绝对是显而易见的方法,也能很好地满足我的需求。但我想知道这样做是否可行。如果可行的话,在某些情况下似乎会非常有用。

***********************编辑**************************

好的,我听取了shiplu.mokadd.im的建议,尝试使用setattr(),但这只对我自己定义的类有效,而对导入的类无效。这里有一个例子:

class pet:
    def __init__(self, name, species):
        self.name = name
        self.species = species

fido = pet('Fido', 'Dog')
setattr(fido, 'breed', 'Golden Retriever')

print fido.breed

这会输出“金毛猎犬”,正如预期的那样。然而这个例子:

import pygame

pygame.init()

rect = pygame.Rect(0, 10, 20, 30)

setattr(rect, 'color', "BLACK")
print rect.color

却输出了这个错误。

Traceback (most recent call last):
  File "game.py", line 7, in <module>
    setattr(rect, 'color', "BLACK")
AttributeError: 'pygame.Rect' object has no attribute 'color'

我意识到我应该这样做:

class ColoredRect(Rect):
    def __init__(self, color, ...):
        self.color = color
        super(ColoredRed, self).__init__(self, ...)

但我想知道,像我之前尝试的那样添加属性是否可能

另外,我希望审核“可能重复”问题的人能明白,我并不是想添加一个方法... =)

1 个回答

3

是的,你可以给实例和类添加属性(因为类本身也是一个对象)。只需要使用 setattr 就可以了。

不过,为什么要这样做呢?你应该继承 Rect 类,然后创建一个 ColoredRect 类。

class ColoredRect(Rect):
    def __init__(self, color, ...):
        self.color = color
        super(ColoredRed, self).__init__(self, ...)

撰写回答