Мне всегда казалось странным, что random.randint(a, b)
вернет целое число в диапазоне [a, b]
вместо [a, b-1]
как range(...)
.
Есть ли причина для этой очевидной несогласованности?
Мне всегда казалось странным, что random.randint(a, b)
вернет целое число в диапазоне [a, b]
вместо [a, b-1]
как range(...)
.
Есть ли причина для этой очевидной несогласованности?
Я попытался разобраться в этом, изучив некоторые старые источники. Я подозревал, что randint
был реализован до длинного целого Python: это означает, что если вы хотите случайное число, включающее INT_MAX
, вам нужно было бы вызвать random.randrange(0, INT_MAX + 1)
, который переполнился бы и привел бы к аргументам (0, 0)
или (0, INT_MIN)
зависит.
Однако, глядя еще в источники Python 1.5.2, в Lib/whrandom.py
мы видим:
#
# Get a random integer in the range [a, b] including both end points.
# (Deprecated; use randrange below.)
#
def randint(self, a, b):
return self.randrange(a, b+1)
whrandom.randint
продолжал оставаться устаревшим в 2.0, 2.1, 2.2 и 2.3; но random.randint
отмечен как устаревший в 2.1, хотя он больше не отмечен как устаревший в 2,2.
Кроме того, random.py
из версии 2.1 является первым, чтобы отметить в random.randint
docstring:
def randrange(self, start, stop=None, step=1, int=int, default=None):
"""Choose a random item from range(start, stop[, step]).
This fixes the problem with randint() which includes the
endpoint; in Python this is usually not what you want.
Do not supply the 'int' and 'default' arguments.
"""
Единственный доступный источник, более старый, чем источник 0.9.1, и насколько я могу судить, randint
не был реализован в этот момент.
Таким образом, я пришел к выводу, что аргументация randint
, включая конечную точку, известна только самому Гвидо; с учетом docstring из Python 2.1, это звучит так, что причина могла быть простой ошибкой.
Думаю, random.randint
была первой попыткой реализовать эту функцию. Похоже, разработчики Python также чувствовали, что это проблема, поэтому в версии 1.5.2 они добавили еще один метод randrange с более стандартным параметры:
random.randrange([start], stop[, step])
Возвращает случайно выбранный элемент из диапазона (начало, остановка, шаг). Это эквивалентно выбору (диапазон (начало, остановка, шаг)), но фактически не создает объект диапазона.
Вы можете использовать randrange
вместо randint
, чтобы избежать неожиданных людей.
С другой стороны, во многих ситуациях, когда проблема формулируется как "выбирать случайное число между 1 и 6", более естественно использовать randint(1, 6)
вместо записи randrange(1, 7)
или randrange(min, max + 1)
.
Это предположение, но нормальное использование человеком "дать мне случайное число от a до b" включено. Реализация его таким образом имеет смысл, учитывая общую философию Питона о том, чтобы быть более понятным для человека языком.
Я не думаю, что есть причина для этого. Но, по крайней мере, это задокументировано.