我想为实数的间隔制作一个Python类。与数学符号最密切相关的语法是Interval([a, b))
,或者甚至更好,Interval[a, b)
来构造满足x
的所有真实a <= x < b
的区间。
是否可以构造一个可以处理这种语法的类?
答案 0 :(得分:4)
无法修复&#34;通过创建自定义类,语法上无效的python。
我认为你在python中最接近数学区间符号的是
Interval('[a, b)')
如果您将间隔作为参数传递给函数,并且函数在使用它们之前将其参数转换为适当的类型,则这种方式会变得更加轻量级。例如:
def do_foo(interval, bar, baz):
interval = Interval(interval)
# do stuff
do_foo('[3,4)', 42, true)
import re
class Interval:
def __init__(self, interval):
"""Initialize an Interval object from a string representation of an interval
e.g: Interval('(3,4]')"""
if isinstance(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 is None:
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 instead
def __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:
return True
if number == self.begin:
return self.begin_included
if number == self.end:
return self.end_included
答案 1 :(得分:1)
您无法更改Python现有的语法规则(无需更改整个语言),但您可以接近您想要的内容:
class Interval(object):
def __init__(self, left_bracket, a, b, right_bracket):
if len(left_bracket) !=1 or left_bracket not in '[(':
raise ValueError(
'Unknown left bracket character: {!r}'.format(left_bracket))
if len(right_bracket) !=1 or right_bracket not in '])':
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 interval
print('{} in {}? {}'.format(3, interval1, 3 in interval1))
print('{} in {}? {}'.format(3, interval2, 3 in interval2))
输出:
3 in [1, 3]? True
3 in [1, 3)? False
注意:a
和b
参数可以是任何可以比较的类型。
答案 2 :(得分:0)
你不能使这个确切的语法工作。但是你可以通过覆盖相关的比较方法来做这样的事情:
a <= Interval() < b
然后,整个表达式可以返回一个新的Interval
对象,其中包含大于或等于a且严格小于b的所有内容。 Interval()
本身可以解释为从负无穷大到正无穷大的完全开放区间(即所有实数的无界区间),而Interval() < b
本身可以指从上方但不是从下方。
NumPy使用类似的技术进行数组比较操作(其中A&lt; B表示&#34;返回1和0的数组,对应于A的每个元素是否小于B&#34的相应元素;)