Search code examples
python-3.xpygamesetattr

python __setattr__ causes attribute error on a defined variable


Every time the 'setattr' magic method is called it causes an attribute error for some reason. I'm getting an attribute error saying the 'rect' variable doesn't exist but it's clearly defined in the class.

import pygame as pg


class Block:
    blocks = {}
    id_ = 1

    def __init__(self, surface, name=None, color=[0] * 3, width=0):
        self.surface = surface
        self.name = (name if name else Block.id_)
        self.color = color
        self.width = width

        self.rect = pg.Rect((0, 0), [20] * 2)
        self.block = self.make_block()

        pg.draw.polygon(*self.block)

        Block.blocks[self.name] = self

        if not name:
            Block.id_ += 1

    def make_block(self):
        point_1 = self.rect.topleft
        point_2 = (self.rect.topleft[0], self.rect.topleft[1] + self.rect.size[1])
        point_3 = (point_2[0] + self.rect.size[0], point_2[1])
        point_4 = (point_3[0], point_1[0])

        return [self.surface, self.color, (point_1, point_2, point_3, point_4), self.width]

    def __setattr__(self, name, value):
        pass


Block(pg.Surface((20, 20)))

Solution

  • You overrode __setattr__ to do nothing. That is where the attribute would be set. Take this small example:

    In [3]: class Rect:
       ...:     def __init__(self):
       ...:         self.length = 12
       ...:         self.width = 5
       ...:     def __setattr__(self, name, val):
       ...:         print(f"attempting to set {name}={val}")
       ...:
    
    In [4]: r=Rect()
    attempting to set length=12
    attempting to set width=5
    
    In [5]: r.length
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-5-1697af2cfc88> in <module>
    ----> 1 r.length
    
    AttributeError: 'Rect' object has no attribute 'length'
    

    Because I override it and don't actually set it, there's no attributes being set for my class. So when I try to access it, it will cause an error. I'm guessing that is what you're experiencing. If you want to fix that then you need to set the attribute when you override it and not just pass.