Skip to content

Commit ccff52e

Browse files
Fallaback to int().
1 parent 9f81ab8 commit ccff52e

File tree

5 files changed

+60
-23
lines changed

5 files changed

+60
-23
lines changed

Doc/library/random.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ Functions for integers
130130
values. Formerly it used a style like ``int(random()*n)`` which could produce
131131
slightly uneven distributions.
132132

133+
.. deprecated:: 3.9
134+
Accepting non-integer arguments is deprecated.
135+
136+
133137
.. function:: randint(a, b)
134138

135139
Return a random integer *N* such that ``a <= N <= b``. Alias for

Doc/whatsnew/3.9.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,9 @@ Deprecated
612612
by :c:func:`Py_Initialize()` since Python 3.7.
613613
(Contributed by Victor Stinner in :issue:`39877`.)
614614

615+
* Deprecated support of non-integer arguments in :func:`random.randrange`.
616+
(Contributed by Serhiy Storchaka in :issue:`37319`.)
617+
615618

616619
Removed
617620
=======

Lib/random.py

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
SG_MAGICCONST = 1.0 + _log(4.5)
6969
BPF = 53 # Number of bits in a float
7070
RECIP_BPF = 2**-BPF
71-
71+
_ONE = 1
7272

7373
# Translated by Guido van Rossum from C source provided by
7474
# Adrian Baddeley. Adapted by Raymond Hettinger for use with
@@ -209,7 +209,7 @@ def __reduce__(self):
209209

210210
## -------------------- integer methods -------------------
211211

212-
def randrange(self, start, stop=None, step=1, _index=_index):
212+
def randrange(self, start, stop=None, step=_ONE, _index=_index, _int=int):
213213
"""Choose a random item from range(start, stop[, step]).
214214
215215
This fixes the problem with randint() which includes the
@@ -219,33 +219,55 @@ def randrange(self, start, stop=None, step=1, _index=_index):
219219

220220
# This code is a bit messy to make it fast for the
221221
# common case while still doing adequate error checking.
222-
start = _index(start)
222+
try:
223+
istart = _index(start)
224+
except TypeError:
225+
istart = _int(start)
226+
if istart != start:
227+
raise ValueError("non-integer arg 1 for randrange()")
228+
_warn('non-integer arg 1 for randrange()',
229+
DeprecationWarning, 2)
223230
if stop is None:
224-
if start > 0:
225-
return self._randbelow(start)
231+
if istart > 0:
232+
return self._randbelow(istart)
226233
raise ValueError("empty range for randrange()")
227234

228235
# stop argument supplied.
229-
stop = _index(stop)
230-
width = stop - start
231-
if step == 1 and width > 0:
232-
return start + self._randbelow(width)
233-
if step == 1:
234-
raise ValueError("empty range for randrange() (%d, %d, %d)" % (start, stop, width))
236+
try:
237+
istop = _index(stop)
238+
except TypeError:
239+
istop = _int(stop)
240+
if istop != stop:
241+
raise ValueError("non-integer stop for randrange()")
242+
_warn('non-integer stop for randrange()',
243+
DeprecationWarning, 2)
244+
width = istop - istart
245+
# Fast path.
246+
if step is _ONE:
247+
if width > 0:
248+
return istart + self._randbelow(width)
249+
raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
235250

236251
# Non-unit step argument supplied.
237-
step = _index(step)
238-
if step > 0:
239-
n = (width + step - 1) // step
240-
elif step < 0:
241-
n = (width + step + 1) // step
252+
try:
253+
istep = _index(step)
254+
except TypeError:
255+
istep = _int(step)
256+
if istep != step:
257+
raise ValueError("non-integer step for randrange()")
258+
_warn('non-integer step for randrange()',
259+
DeprecationWarning, 2)
260+
if istep > 0:
261+
n = (width + istep - 1) // istep
262+
elif istep < 0:
263+
n = (width + istep + 1) // istep
242264
else:
243265
raise ValueError("zero step for randrange()")
244266

245267
if n <= 0:
246268
raise ValueError("empty range for randrange()")
247269

248-
return start + step*self._randbelow(n)
270+
return istart + istep*self._randbelow(n)
249271

250272
def randint(self, a, b):
251273
"""Return random integer in range [a, b], including both end points.

Lib/test/test_random.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -367,15 +367,22 @@ def test_randrange_errors(self):
367367
raises(3, 3)
368368
raises(-721)
369369
raises(0, 100, -12)
370+
self.assertWarns(DeprecationWarning, raises, 3, 3, 1.0)
370371
# Non-integer start/stop
371-
self.assertRaises(TypeError, self.gen.randrange, 3.0)
372-
self.assertRaises(TypeError, self.gen.randrange, Fraction(3, 1))
373-
self.assertRaises(TypeError, self.gen.randrange, 0, 2.0)
374-
self.assertRaises(TypeError, self.gen.randrange, 0, Fraction(2, 1))
372+
raises(3.14159)
373+
self.assertWarns(DeprecationWarning, self.gen.randrange, 3.0)
374+
self.assertWarns(DeprecationWarning, self.gen.randrange, Fraction(3, 1))
375+
raises('3')
376+
raises(0, 2.71828)
377+
self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 2.0)
378+
self.assertWarns(DeprecationWarning, self.gen.randrange, 0, Fraction(2, 1))
379+
raises(0, '2')
375380
# Zero and non-integer step
376381
raises(0, 42, 0)
377-
self.assertRaises(TypeError, self.gen.randrange, 0, 42, 3.0)
378-
self.assertRaises(TypeError, self.gen.randrange, 0, 42, Fraction(3, 1))
382+
raises(0, 42, 3.14159)
383+
self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, 3.0)
384+
self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, Fraction(3, 1))
385+
raises(0, 42, '3')
379386

380387
def test_genrandbits(self):
381388
# Verify ranges
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Deprecated support of non-integer arguments in :func:`random.randrange`.

0 commit comments

Comments
 (0)