Notation For Intervals?
Solution 1:
It's impossible to "fix" syntactically invalid python by making a custom class.
I think the closest you can get to the mathematical interval notation in python is
Interval('[a, b)')
This way becomes even more lightweight if you are passing intervals as arguments to a function and the function converts it's arguments to an appropriate type before using them. Example:
def do_foo(interval, bar, baz):
interval=Interval(interval)
# do stuff
do_foo('[3,4)', 42, true)
import re
classInterval:
def__init__(self, interval):
"""Initialize an Interval object from a string representation of an interval
e.g: Interval('(3,4]')"""ifisinstance(interval, Interval):
self.begin, self.end = interval.begin, interval.end
self.begin_included = interval.begin_included
self.end_included = interval.end_included
return
number_re = '-?[0-9]+(?:.[0-9]+)?'
interval_re = ('^\s*'
+'(\[|\()'# opeing brecket
+ '\s*'
+ '(' + number_re + ')'# beginning of the interval
+ '\s*,\s*'
+ '(' + number_re + ')'# end of the interval
+ '\s*'
+ '(\]|\))'# closing brecket
+ '\s*$'
)
match = re.search(interval_re, interval)
if match isNone:
raise ValueError('Got an incorrect string representation of an interval: {!r}'. format(interval))
opening_brecket, begin, end, closing_brecket = match.groups()
self.begin, self.end = float(begin), float(end)
if self.begin >= self.end:
raise ValueError("Interval's begin shoud be smaller than it's end")
self.begin_included = opening_brecket == '['
self.end_included = closing_brecket == ']'# It might have been batter to use number_re = '.*' and catch exeptions float() raises insteaddef__repr__(self):
return'Interval({!r})'.format(str(self))
def__str__(self):
opening_breacket = '['if self.begin_included else'('
closing_breacket = ']'if self.end_included else')'return'{}{}, {}{}'.format(opening_breacket, self.begin, self.end, closing_breacket)
def__contains__(self, number):
if self.begin < number < self.end:
returnTrueif number == self.begin:
return self.begin_included
if number == self.end:
return self.end_included
Solution 2:
You can't change Python's existing syntax rules (without changing the whole language), but you can get usably close to what you want:
classInterval(object):
def__init__(self, left_bracket, a, b, right_bracket):
iflen(left_bracket) !=1or left_bracket notin'[(':
raise ValueError(
'Unknown left bracket character: {!r}'.format(left_bracket))
iflen(right_bracket) !=1or right_bracket notin'])':
raise ValueError(
'Unknown right bracket character: {!r}'.format(right_bracket))
if a < b:
self.lower, self.upper = a, b
else:
self.lower, self.upper = b, a
self.left_bracket, self.right_bracket = left_bracket, right_bracket
if left_bracket == '[':
if right_bracket == ']':
self._contains = (
lambda self, val: self.lower <= val <= self.upper)
else:
self._contains = (
lambda self, val: self.lower <= val < self.upper)
else:
if right_bracket == ']':
self._contains = (
lambda self, val: self.lower < val <= self.upper)
else:
self._contains = (
lambda self, val: self.lower < val < self.upper)
__contains__ = lambda self, val: self._contains(self, val)
def__str__(self):
return'{}{}, {}{}'.format(self.left_bracket, self.lower, self.upper,
self.right_bracket)
def__repr__(self):
return'{}({!r}, {}, {}, {!r})'.format(self.__class__.__name__,
self.left_bracket, self.lower, self.upper, self.right_bracket)
if __name__ == '__main__':
interval1 = Interval('[', 1, 3, ']') # closed interval
interval2 = Interval('[', 1, 3, ')') # half-open intervalprint('{} in {}? {}'.format(3, interval1, 3in interval1))
print('{} in {}? {}'.format(3, interval2, 3in interval2))
Output:
3 in [1, 3]? True
3 in [1, 3)? False
Note: The a
and b
arguments can be any type that can be compared.
Solution 3:
You cannot make this exact syntax work. But you could do something like this by overriding the relevant comparison methods:
a <=Interval() < b
This whole expression could then return a new Interval
object that includes everything greater than or equal to a and strictly less than b. Interval()
by itself could be interpreted as the fully open interval from negative to positive infinity (i.e. the unbounded interval of all real numbers), and Interval() < b
by itself could refer to an interval bounded from above but not from below.
NumPy uses a similar technique for array comparison operations (where A < B means "return an array of ones and zeros that correspond to whether or not each element of A is less than the respective element of B").
Post a Comment for "Notation For Intervals?"