@@ -14,30 +14,46 @@ import numbers
14
14
_VALID_CLOSED = frozenset ([' left' , ' right' , ' both' , ' neither' ])
15
15
16
16
17
- cdef class IntervalMixin:
18
- property closed_left :
19
- def __get__ (self ):
20
- return self .closed == ' left' or self .closed == ' both'
21
-
22
- property closed_right :
23
- def __get__ (self ):
24
- return self .closed == ' right' or self .closed == ' both'
25
-
26
- property open_left :
27
- def __get__ (self ):
28
- return not self .closed_left
29
-
30
- property open_right :
31
- def __get__ (self ):
32
- return not self .closed_right
33
-
34
- property mid :
35
- def __get__ (self ):
36
- try :
37
- return 0.5 * (self .left + self .right)
38
- except TypeError :
39
- # datetime safe version
40
- return self .left + 0.5 * (self .right - self .left)
17
+ cdef class IntervalMixin(object ):
18
+
19
+ @property
20
+ def closed_left (self ):
21
+ """
22
+ Return True if the Interval is closed on the left-side, else False
23
+ """
24
+ return self .closed in (' left' , ' both' )
25
+
26
+ @property
27
+ def closed_right (self ):
28
+ """
29
+ Return True if the Interval is closed on the right-side, else False
30
+ """
31
+ return self .closed in (' right' , ' both' )
32
+
33
+ @property
34
+ def open_left (self ):
35
+ """
36
+ Return True if the Interval is open on the left-side, else False
37
+ """
38
+ return not self .closed_left
39
+
40
+ @property
41
+ def open_right (self ):
42
+ """
43
+ Return True if the Interval is open on the right-side, else False
44
+ """
45
+ return not self .closed_right
46
+
47
+ @property
48
+ def mid (self ):
49
+ """
50
+ Return the midpoint of the Interval
51
+ """
52
+ try :
53
+ return 0.5 * (self .left + self .right)
54
+ except TypeError :
55
+ # datetime safe version
56
+ return self .left + 0.5 * (self .right - self .left)
41
57
42
58
43
59
cdef _interval_like(other):
@@ -55,12 +71,12 @@ cdef class Interval(IntervalMixin):
55
71
Parameters
56
72
----------
57
73
left : value
58
- Left bound for interval.
74
+ Left bound for the interval
59
75
right : value
60
- Right bound for interval.
61
- closed : {'left', 'right', 'both', 'neither'}
76
+ Right bound for the interval
77
+ closed : {'left', 'right', 'both', 'neither'}, default 'right'
62
78
Whether the interval is closed on the left-side, right-side, both or
63
- neither. Defaults to 'right'.
79
+ neither
64
80
65
81
Examples
66
82
--------
@@ -77,20 +93,30 @@ cdef class Interval(IntervalMixin):
77
93
78
94
See Also
79
95
--------
80
- IntervalIndex : an Index of ``interval`` s that are all closed on the same
81
- side.
82
- cut, qcut : convert arrays of continuous data into categoricals/series of
83
- `` Interval`` .
96
+ IntervalIndex : An Index of Interval objects that are all closed on the
97
+ same side.
98
+ cut, qcut : Convert arrays of continuous data into Categoricals/Series of
99
+ Interval.
84
100
"""
85
101
86
- cdef readonly object left, right
102
+ cdef readonly object left
103
+ """ Left bound for the interval"""
104
+
105
+ cdef readonly object right
106
+ """ Right bound for the interval"""
107
+
87
108
cdef readonly str closed
109
+ """
110
+ Whether the interval is closed on the left-side, right-side, both or
111
+ neither
112
+ """
88
113
89
114
def __init__ (self , left , right , str closed = ' right' ):
90
115
# note: it is faster to just do these checks than to use a special
91
116
# constructor (__cinit__/__new__) to avoid them
92
117
if closed not in _VALID_CLOSED:
93
- raise ValueError (" invalid option for 'closed': %s " % closed)
118
+ msg = " invalid option for 'closed': {closed}" .format(closed = closed)
119
+ raise ValueError (msg)
94
120
if not left <= right:
95
121
raise ValueError (' left side of interval must be <= right side' )
96
122
self .left = left
@@ -122,10 +148,11 @@ cdef class Interval(IntervalMixin):
122
148
if op == Py_EQ or op == Py_NE:
123
149
return NotImplemented
124
150
else :
151
+ name = type (self ).__name__
152
+ other = type (other).__name__
125
153
op_str = {Py_LT: ' <' , Py_LE: ' <=' , Py_GT: ' >' , Py_GE: ' >=' }[op]
126
- raise TypeError (
127
- ' unorderable types: %s () %s %s ()' %
128
- (type (self ).__name__, op_str, type (other).__name__))
154
+ raise TypeError (' unorderable types: {name}() {op} {other}()'
155
+ .format(name = name, op = op_str, other = other))
129
156
130
157
def __reduce__ (self ):
131
158
args = (self .left, self .right, self .closed)
@@ -145,15 +172,18 @@ cdef class Interval(IntervalMixin):
145
172
def __repr__ (self ):
146
173
147
174
left, right = self ._repr_base()
148
- return (' %s (%r , %r , closed=%r )' %
149
- (type (self ).__name__, left, right, self .closed))
175
+ name = type (self ).__name__
176
+ repr_str = ' {name}({left!r}, {right!r}, closed={closed!r})' .format(
177
+ name = name, left = left, right = right, closed = self .closed)
178
+ return repr_str
150
179
151
180
def __str__ (self ):
152
181
153
182
left, right = self ._repr_base()
154
183
start_symbol = ' [' if self .closed_left else ' ('
155
184
end_symbol = ' ]' if self .closed_right else ' )'
156
- return ' %s%s , %s%s ' % (start_symbol, left, right, end_symbol)
185
+ return ' {start}{left}, {right}{end}' .format(
186
+ start = start_symbol, left = left, right = right, end = end_symbol)
157
187
158
188
def __add__ (self , y ):
159
189
if isinstance (y, numbers.Number):
@@ -222,8 +252,8 @@ cpdef intervals_to_interval_bounds(ndarray intervals):
222
252
continue
223
253
224
254
if not isinstance (interval, Interval):
225
- raise TypeError (" type {} with value {} is not an interval" .format(
226
- type (interval), interval))
255
+ raise TypeError (" type {typ } with value {iv } is not an interval"
256
+ .format( typ = type (interval), iv = interval))
227
257
228
258
left[i] = interval.left
229
259
right[i] = interval.right
0 commit comments