'Python AttributeError When Attribute is Set

I am creating a snake clone using pygame and I am running into a strange problem. I have a class called snake_tile that inherits from the pygame rectangle class with one additional attribute, the direction the tile is moving:

import pygame

class snake_tile(pygame.Rect):
    def __init__(self, left, top, width, height, direction):
        super().__init__(left, top, width, height)
        self.direction = direction

I pass in a tuple as the direction when initializing the snake_tile object:

snake_head = snake_tile(snake_tile_x, snake_tile_y, 10, 10, (0,0))

Which will serve as the offset when I move the tile later on, as the pygame.Rect.move() function takes in an x and y offset:

snake_head = snake_head.move(snake_head.direction[0], snake_head.direction[1])
   

However, when I attempt to move the tile like above I get this error:

AttributeError: 'snake_tile' object has no attribute 'direction'

But when I try something like this:

print(snake_head.direction)
snake_head = snake_head.move(snake_head.direction[0], snake_head.direction[1])

I get the output:

(0, 0)
AttributeError: 'snake_tile' object has no attribute 'direction'

So it seems as though the direction attribute is correctly being set, but when I try to access is again to move the snake head I get an attribute error.

Any ideas?



Solution 1:[1]

pygame.Rect.move does not change the rectangle object in place: it creates a new object and returns that new instance.

Although it plays well with inheritance: i.e. it returns a new instance of any subclass, and not a plain Rect, it won't set the .direction attribute on it.

Your work around is as simple as setting the direction attribute in your subclass' .move method:

class snake_tile(pygame.Rect):
    def __init__(self, left, top, width, height, direction):
        super().__init__(left, top, width, height)
        self.direction = direction

    def move(self, *args, **kw):
        new_instance = super().move(*args, **kw) # we don't care which arguments are passed
        new_instance.direction = self.direction
        return new_instance

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jsbueno