DJMcMayhem
DJMcMayhem

Reputation: 7679

Is it possible to add an attribute to an imported class in python?

I will explain my situation so that my question makes more sense.

I am programming a game using python and pygame. It is a pretty minimalist game without a lot of graphics, and I want each level to be a grid of either black or white squares. I think it makes a lot more sense to have each level be defined as a string of 1's and 0's like so

0000
0101
1010
1111

as opposed to:

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),
...
...

and so on and so forth for every single rect. The second way is clunky and awkward, and would make it very difficult to design the levels. Also in python, readability counts, and beautiful is better than ugly. =)

I am planning on using the first way, and having a function that returns a list of pygame.Rect objects (similar to the code above) where the 0's are black tiles, and the 1's are white tiles. Unfortunately though, pygame.Rect objects don't contain any data about what color they are.

Now my question is two-fold.

1) Is it possible to add an attribute to an existing class (In this example, adding the attribute rect.color) without going into the source code of the module it came from and changing it yourself? (Becuase that seems like a REALLY bad idea.)

2) If the above is possible, is it wise? Or are you just shooting yourself in the foot?

Understand of course, I realize that this is not the only way to accomplish what I want. If I wanted to do it the tried and true way, I would create a class like so:

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)

This is definitely the obvious way, and works for what I need just fine. But, I would like to know whether or not this is possible. If it is, it seems like it could be very useful in certain situations.

***********************EDIT**************************

Okay, I took shiplu.mokadd.im's advice and tried using setattr(), but that only works with classes that I have defined myself, not imported classes. Here is an example:

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

which outputs "Golden Retriever" as expected. However this example:

import pygame

pygame.init()

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

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

outputs this error.

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

I realize that I should just do this:

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

but is it possible to add an attribute the way I've been trying?

Also, I hope that whoever reviews the "Possible Duplicate" questions, realizes that I'm not trying to add a method... =)

Upvotes: 3

Views: 2810

Answers (1)

Shiplu Mokaddim
Shiplu Mokaddim

Reputation: 57650

Yes its possible to add attribute to instances and classes (as its an object too). Just use setattr.

But why do you do that? you should inherit the Rect class and make a ColoredRect

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

Upvotes: 3

Related Questions