Context: I’m making a game that happens in a maze made of square tiles and almost everything, from movement to attacks, involves directions, which are mostly used to index lists. Subtracting or adding to directions is an easy way to turn left or right, but I always have to check that they are still within bounds, and I would like to automate that by making a custom class.
Here is how I’m currently doing it:
global UP UP = 0 global RIGHT RIGHT = 1 global DOWN DOWN = 2 global LEFT LEFT = 3
And here is what I’d like to do:
class Direction: number_of_directions=4 def __init__(self,direction): self.direction = direction def __int__(self): return self.direction def __add__(self,other): #Here other is supposed to be an int return (self.direction + other)%number_of_directions def __sub__(self,other): #Here other is supposed to be an int return (self.direction - other)%number_of_directions global UP UP = Direction(0) global LEFT LEFT = Direction(1) global DOWN DOWN = Direction(2) global RIGHT RIGHT = Direction(3)
The only problem with that is that I am using UP
, RIGHT
, etc. as indexes, like I have a Tile
that has a list of four Wall
and I constantly call Tile.walls[direction]
with direction being one of my four constants, and I don’t want to have to specify Tile.walls[int(direction)]
everytime.
Is there a way to have direction
automatically coerced into an int whenever it’s used for indexing?
Advertisement
Answer
Yes, simply define __index__()
. For example:
class Direction: def __init__(self, direction): self.direction = direction def __index__(self): return self.direction UP = Direction(0) cardinals = ['north', 'east', 'south', 'west'] print(cardinals[UP]) # -> north
This also makes __int__
unnecessary since __index__
is used as a fallback.
print(int(UP)) # -> 0
P.S. For this answer, I’m ignoring any design considerations. Using an IntEnum
might be a better solution, I’m not sure.