0

here is my code :

size = (1280, 850)
Win = pygame.display.set_mode(size)
class Particle:
    color = (255, 255, 0)
    ID = 0

    def __init__(self, rect):
        Particle.ID += 1
        self.color = (color)
        self.ID = Particle.ID
        self.rect = rect

    def move(self, x, y):
        self.rect.move(x, y)

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

    def collide(self, rect1):
        return self.rect.colliderect(rect1)

When I run my project, I have : "self.color = (color) NameError: name 'color' is not defined" but color is defined...It is at the beginning of my class "Particle"...

Thank you to help me !

  • 2
    `color` -> `self.__class__.color` to access the class variable. It is not a good idea to name an instance variable like a class variable - this easiliy leads to errors. – MrBean Bremen Feb 17 '20 at 12:36
  • 2
    What are you trying to do? You have the color as a class variable, and then you are trying to assign an instance variable with the same name? – macro_controller Feb 17 '20 at 12:38
  • Or just `self.color` –  Feb 17 '20 at 12:38
  • Your problem is that there is no symbol named `color` in your `__init__` function, but I have the feeling you try to achieve something else there. – macro_controller Feb 17 '20 at 12:39
  • 1
    You don't have variable 'color' in your __init__, so it's senseless to assign class variable to instance variable - it will have it by default. But you can do something like MyParticle = Particle(some_rect) – Hyyudu Feb 17 '20 at 12:42
  • 1
    The `color` class attribute will be accessible for all its instances, no need to define it in the `__init__` method. If you want to create another variable based on `color`, please rename it. It you want to get the `rect` color, you can write `self.color = rect.color`. – Frodon Feb 17 '20 at 12:43
  • 1
    Does this answer your question? [What is the difference between class and instance attributes?](https://stackoverflow.com/questions/207000/what-is-the-difference-between-class-and-instance-attributes) – Maurice Meyer Feb 17 '20 at 12:51

6 Answers6

3

The fact you defined color in the class's namespace (making it a class attribute) doesn't make it available in methods bodies. Names in a method (actually a function) body are resolved at function execution time, not at function definition time, and at this point the color varibale defined in the class body has already be turned into a class attributes - they are not part of the function's non-local namespace.

Now the "proper" solution depends on what you want to achieve.

If all of your particle instance should share the same "color" value, just keep the class attribute and remove the instance one in your initializer - class attributes can be accessed directly from the instances, so self.color will automagically resolve to type(self).color. Note that this won't prevent you to assign per-instance color values - the class attribute is only accessed thru the instance if the instance has no attribute by that name, so setting your_particle.color = something_else (or self.color = ... - just the same) later in your code will still create an instance attribute and shadow the class-level one - but this is usually considered bad practice as it doesn't make the intent clear.

If you want per-instance colors, the best solution is to get rid of the class level attribute and only set the color in the initializer ie

class Particle:

    # better to make this an implementation attribute
    _ID = 0

    @classmethod
    def _next_id(cls):
        cls._ID += 1
        return cls._ID

    def __init__(self, rect):
        self.ID = self._next_id()
        self.color = (255, 0, 0)

or (if you want to be able to specify the color at instantiation time):

    def __init__(self, rect, color=(255, 0, 0)):
        self.ID = self._next_id()
        self.color = color
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
1

Technically spoken: You dont need the instance attributes, color and ID are already available:

class Particle:
    color = (255, 255, 0)
    ID = 0

    def __init__(self, rect):
        Particle.ID += 1
        self.rect = rect

        print(self.ID)
        print(self.color)

p = Particle(None)

Output:

1
(255, 255, 0)

Note: In case you really need color and ID as instance variables, use a another name:

class Particle:
    color = (255, 255, 0)
    ID = 0
    def __init__(self, rect):
        Particle.ID += 1
        self.rect = rect
        self.pcolor = self.color
        self.pID = self.ID
Maurice Meyer
  • 17,279
  • 4
  • 30
  • 47
0

Remove the line self.color = (color) in order to make your code working.

B--rian
  • 5,578
  • 10
  • 38
  • 89
Maximouse
  • 4,170
  • 1
  • 14
  • 28
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. - [From Review](/review/low-quality-posts/25376377) – Simas Joneliunas Feb 17 '20 at 13:35
  • @SimasJoneliunas This *is* an answer. See B--rian's edit. – Maximouse Feb 17 '20 at 14:28
0

You don't have variable color in your __init__(), so it's senseless to assign class variable to instance variable - it will have it by default. But you can do something like

MyParticle = Particle(some_rect)
MyParticle.color = (255, 0, 255)
Ahmad Farhan
  • 575
  • 4
  • 12
Hyyudu
  • 134
  • 1
  • 7
  • I did this : `class Particle: color = (255, 255, 0) def __init__(self, rect): self.color = self.color` –  Feb 17 '20 at 12:44
0

A couple comments. Since you define color as a class variable, you probably don't want to reassign it as an instance variable. Just use it directly with Particle.color (see draw below). If you want to keep track of IDs you can just use id(object). You can use your existing strategy for ID as a count though.

class Particle:
    color = (255, 255, 0)

    def __init__(self, rect):
        self.rect = rect

    def move(self, x, y):
        self.rect.move(x, y)

    def draw(self):
        print(Particle.color, self.rect) # pygame.draw.rect

p = Particle("Rectangle dimensions")                                   
id(p)                                                                  
> 4559902608

p2 = Particle("Rectangle dimensions")
id(p2)
> 4559964496
Kent Shikama
  • 3,910
  • 3
  • 22
  • 55
-4

I cannot comment yet.

Try this:

self.color = (color) -> self.color = color

Edit: Let me correct, I do not have the full context of your implementation of the class. You have to initialize the class as an object because the funciton draw cals the color in the self container. Hence you have to create the object, then call the draw function from the object. Thus Particle.draw() will not work because the classes initializer is not called.

Thus:

particle = Particle()
particle.draw()
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
mrb
  • 3
  • 2
  • You should still be able to try it out in an online editor like ideone or repl.it. – Sayse Feb 17 '20 at 12:44
  • Let me correct, I do not have the full context of your implementation of the class. You have to initialize the class as an object because the funciton draw cals the color in the self container. Hence you have to create the object, then call the draw function from the object. Thus Particle.draw() will not work because the classes initializer is not called. – mrb Feb 17 '20 at 12:44
  • If you cannot comment yet, it's better to invest 15 minutes to get the minimum rep required, rather than to post a non-answer. Also, we're not going to "bare" with you. :laugh: – Jonathan Hall May 02 '20 at 17:22