'How to create a static instance of a class when it would lead to an exception in the constructor?
I have the following code:
class Position:
def __int__(self, x: int, y: int):
if out_of_range(x, 0, MAX_INT - 1):
raise ValueError("[error][{}.{}()] Failed to create position: {}\n".format(__class__,
inspect.stack()[0].function,
"x must be in range [0, MAX_INT)"
))
if out_of_range(y, 0, MAX_INT - 1):
raise ValueError("[error][{}.{}()] Failed to create position: {}\n".format(__class__,
inspect.stack()[0].function,
"y must be in range [0, MAX_INT)"
))
self.__x: int = x
self.__y: int = y
And I want to create a static instance of Position, with x and y both equal to MAX_INT.
How can I write the code in order to be able to do this:
if Position(2, 3) == Position.INVALID: # INVALID <=> Position(MAX_INT, MAX_INT)
...
EDIT:
I have another method in the Position class:
def to(self, direction: Direction, steps: int = 1) -> 'Position':
"""
Creates a new position, to the given direction.
If one of the new coordinates goes below 0, then Position.INVALID is returned.
A negative 'steps' value inverses the direction. Ex: Position.to(RIGHT, 3) == Position.to(LEFT, -3)
"""
delta_x, delta_y = DIRECTION_DELTA[direction]
try:
return Position(self.__x + delta_x * steps, self.__y + delta_y * steps)
except ValueError:
return Position.INVALID
More specifically, my intendend usage would be
if Position(2, 3).to(LEFT, 3) == Position.INVALID:
do something
else:
do something else
A 1st aproach would be to add another method which checks if a position is valid.
def to(self, direction: Direction, steps: int = 1) -> 'Position':
"""
Creates a new position, to the given direction.
If one of the new coordinates goes below 0, then Position.INVALID is returned.
A negative 'steps' value inverses the direction. Ex: Position.to(RIGHT, 3) == Position.to(LEFT, -3)
"""
delta_x, delta_y = DIRECTION_DELTA[direction]
try:
return Position(self.__x + delta_x * steps, self.__y + delta_y * steps)
except ValueError:
position: Position = Position(0, 0)
position.__x = MAX_INT
position.__y = MAX_INT
return position
def is_valid() -> bool:
return not self.__x == self.__y == MAX_INT
But now, Position(MAX_INT, MAX_INT) is no longer a singleton.
A 2nd approach would be to let the method to() throw the error from the constructor and catch it outside of Position.to().
Solution 1:[1]
Not really sure if this is what you need but using the decorator @classmethod and defining __eq__ you can create an instance with x=MAX_INT and compare it with your instance:
class Position:
def __init__(self, x: int):
if x > MAX_INT:
raise ValueError
self.__x: int = x
def __eq__(self, other):
if self.__x == other.__x:
return True
return False
@classmethod
def INVALID(cls):
p = Position(0)
p.__x = MAX_INT
return p
def to(self, direction: Direction, steps: int = 1) -> 'Position':
delta_x, delta_y = DIRECTION_DELTA[direction]
try:
return Position(self.__x + delta_x * steps, self.__y + delta_y * steps)
except ValueError:
return Position.INVALID()
if Position(MAX_INT-1) == Position.INVALID():
print('invalid')
else:
print('valid')
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 |
