Reputation: 35
Right now I am creating a class which represents a closed interval. Its core functionality is to provide an intersect
method.
class Interval:
def __init__(self, a, b):
# check a <= b otherwise swap
self.a = a
self.b = b
def intersect(self, other):
a = self.a if self.a > other.a else other.a
b = self.b if self.b < other.b else other.b
if b < a:
# return some value representing an empty interval, providing the intersect method
return Intervall(a,b)
It should be possible to represent special Values like all points [-oo,oo] or the empty set {}. Which still serve the intersect
method. My current approach is to create a new class, but this seems kinda tedious.
class EmptyInterval:
def intersect(self, other):
return self
Assuming those special values' intersect methods take precedence I'd prepend on the Intervall class' method:
class Intervall:
...
def intersect(self,other):
if not isinstance(self, other):
other.intersect(self)
...
To clarify - the following should be legal:
a = Intervall(1,2)
b = Intervall(3,4)
c = a.intersect(b) # resulting in an empty interval
c.intersect(a) # resulting again in an empty interval
Is there some elegant / more pythonic / less nauseating ugly way to implement such a behavior?
First I thought of inheritance, but that seems quite unfitting because of the precedence those special values should have; i.e. I do not know how to implement it via inheritance.
Upvotes: 0
Views: 47
Reputation: 35
Maybe this could be another solution:
Instead of passing a,b separately, I could pass a tuple (a,b). Further I could declare a couple of singletons as class variables. During instantiation I'd pass that singleton and would only have to check whether that value is one of the singletons and act accordingly.
class Interval:
EMPTY = object()
EVERYTHING = object()
def __init__(self, bounds):
self.bound = bounds
def intersect(self, other):
if self.bounds == self.EMPTY or other.bounds == self.EMPTY:
return Interval(self.EMPTY)
...
if b < a:
return Interval(self.EMPTY)
return Interval((a,b))
I guess this maybe less error prone than John's answer, because of the general behavior math.inf and / or math.nan impose. Also it would allow to strictly forbid those values to be passed, as Interval(math.nan, 1) would be nonsensical.
But it may be more effort to implement in a more complex setting.
Upvotes: 0
Reputation: 249153
Define a couple special functions in your class Interval
:
@staticmethod
def everything():
return Interval(-math.inf, math.inf)
@staticmethod
def nothing():
return Interval(math.nan, math.nan)
You may find it more natural to write nothing()
like this:
return Interval(0, 0)
or this:
return Interval(math.inf, math.inf)
It rather depends on your other code, and what you think is the most natural way to represent the empty interval. Note that any less or greater comparison with NAN will return false, so this may have some impact on which way you decide to represent the empty interval (for example is nothing().intersect(nothing())
supposed to be true or false?).
Upvotes: 1