random — генерация псевдослучайных чисел
Исходный код: Lib/random.py
Этот модуль реализует генераторы псевдослучайных чисел для различных распределений.
Для целых чисел доступен равномерный выбор из диапазона. Для последовательностей доступны равномерный выбор случайного элемента, функция для генерации случайной перестановки списка на месте и функция для случайной выборки без возвращения.
Для вещественных чисел доступны функции для вычисления равномерного, нормального (гауссовского), логнормального, отрицательного экспоненциального, гамма- и бета-распределений. Для генерации распределений углов доступно распределение фон Мизеса.
Почти все функции модуля зависят от базовой функции random(), которая генерирует случайное вещественное число с равномерным распределением в полуоткрытом диапазоне 0.0 <= X < 1.0. В качестве основного генератора Python использует вихрь Мерсенна. Он генерирует вещественные числа с точностью 53 бита и имеет период 2**19937-1. Базовая реализация на C работает быстро и является потокобезопасной. Вихрь Мерсенна — один из наиболее тщательно проверенных генераторов случайных чисел. Однако из-за своей полной детерминированности он подходит не для всех задач и совершенно не подходит для криптографических целей.
Функции, предоставляемые этим модулем, на самом деле являются связанными методами скрытого экземпляра класса random.Random. Можно создать собственные экземпляры Random, чтобы получить генераторы с независимым состоянием.
Класс Random также можно наследовать, если вы хотите использовать собственный базовый генератор: дополнительные сведения см. в документации этого класса.
Модуль random также предоставляет класс SystemRandom, который использует системную функцию os.urandom() для генерации случайных чисел из источников, предоставляемых операционной системой.
Предупреждение
Генераторы псевдослучайных чисел этого модуля не следует использовать в целях безопасности. Для задач безопасности и криптографии см. модуль secrets.
См. также
M. Matsumoto и T. Nishimura, «Mersenne Twister: A 623-dimensionally equidistributed uniform pseudorandom number generator», ACM Transactions on Modeling and Computer Simulation, том 8, № 1, январь, с. 3–30, 1998.
Рецепт Complementary-Multiply-with-Carry — совместимый альтернативный генератор случайных чисел с большим периодом и сравнительно простыми операциями обновления.
Примечание
Глобальный генератор случайных чисел и экземпляры Random являются потокобезопасными. Однако в сборке со свободной многопоточностью параллельные вызовы глобального генератора или одного и того же экземпляра Random могут привести к конкуренции за ресурсы и снижению производительности. Рассмотрите возможность использования отдельных экземпляров Random для каждого потока.
Функции управления состоянием
-
random.seed(a=None, version=2) -
Инициализировать генератор случайных чисел.
Если a не указано или равно
None, используется текущее системное время. Если операционная система предоставляет источники случайности, вместо системного времени используются они (сведения о доступности см. в описании функцииos.urandom()).Если a — целое число, оно используется напрямую.
В версии 2 (используется по умолчанию) объект типа
str,bytesилиbytearrayпреобразуется вint, и используются все его биты.В версии 1 (предназначенной для воспроизведения последовательностей случайных чисел из старых версий Python) алгоритм для
strиbytesгенерирует более узкий диапазон начальных значений.Изменено в версии 3.2: Перейдено на схему версии 2, использующую все биты строкового начального значения.
-
random.getstate() -
Вернуть объект, содержащий текущее внутреннее состояние генератора. Этот объект можно передать в
setstate(), чтобы восстановить состояние.
-
random.setstate(state) -
state должен быть получен предыдущим вызовом
getstate(). Функцияsetstate()восстанавливает внутреннее состояние генератора до того, каким оно было во время вызоваgetstate().
Функции для байтов
-
random.randbytes(n) -
Сгенерировать n случайных байтов.
Этот метод не следует использовать для генерации токенов безопасности. Вместо этого используйте
secrets.token_bytes().Добавлено в версии 3.9.
Функции для целых чисел
-
random.randrange(stop) - random.randrange(start, stop[, step])
-
Вернуть случайно выбранный элемент из
range(start, stop, step).Примерно эквивалентно
choice(range(start, stop, step)), но поддерживает сколь угодно большие диапазоны и оптимизировано для распространённых случаев.Шаблон позиционных аргументов соответствует функции
range().Не следует использовать именованные аргументы, поскольку они могут интерпретироваться неожиданным образом. Например,
randrange(start=100)интерпретируется какrandrange(0, 100, 1).Изменено в версии 3.2:
randrange()использует более сложный алгоритм для получения равномерно распределённых значений. Ранее применялся алгоритм видаint(random()*n), который мог приводить к небольшим неравномерностям распределения.Изменено в версии 3.12: Автоматическое преобразование типов, отличных от целочисленных, больше не поддерживается. Такие вызовы, как
randrange(10.0)иrandrange(Fraction(10, 1)), теперь вызывают исключениеTypeError.
-
random.randint(a, b) -
Вернуть случайное целое число N, такое что
a <= N <= b. Псевдоним дляrandrange(a, b+1).
-
random.getrandbits(k) -
Возвращает неотрицательное целое число Python с k случайными битами. Этот метод предоставляется генератором «вихрь Мерсенна»; некоторые другие генераторы также могут реализовывать его как необязательную часть API. Если метод доступен,
getrandbits()позволяет функцииrandrange()обрабатывать сколь угодно большие диапазоны.Изменено в версии 3.9: Теперь этот метод принимает ноль в качестве значения k.
Функции для последовательностей
-
random.choice(seq) -
Вернуть случайный элемент непустой последовательности seq. Если seq пуста, вызывает исключение
IndexError.
-
random.choices(population, weights=None, *, cum_weights=None, k=1) -
Вернуть список из k элементов, выбранных из population с возвращением. Если population пуста, вызывает исключение
IndexError.Если задана последовательность весов weights, выбор выполняется в соответствии с относительными весами. Если задана последовательность cum_weights, выбор выполняется в соответствии с накопленными весами (которые можно вычислить, например, с помощью
itertools.accumulate()). Например, относительные веса[10, 5, 30, 5]эквивалентны накопленным весам[10, 15, 45, 50]. Перед выбором относительные веса внутри функции преобразуются в накопленные, поэтому передача накопленных весов позволяет сэкономить вычисления.Если не указаны ни weights, ни cum_weights, все элементы выбираются с равной вероятностью. Если указана последовательность весов, её длина должна совпадать с длиной последовательности population. Одновременное указание weights и cum_weights приводит к исключению
TypeError.Для weights и cum_weights можно использовать любой числовой тип, совместимый с вещественными значениями
float, возвращаемыми модулемrandom()(включая целые числа, вещественные числа и дроби, но не десятичные числа). Предполагается, что веса неотрицательны и конечны. Если все веса равны нулю, вызывается исключениеValueError.При заданном начальном значении функция
choices()с одинаковыми весами обычно возвращает последовательность, отличающуюся от последовательности, полученной повторными вызовамиchoice(). Алгоритмchoices()использует арифметику с плавающей точкой для внутренней согласованности и скорости. Алгоритмchoice()по умолчанию использует целочисленную арифметику и повторные выборки, чтобы избежать небольших смещений из-за ошибок округления.Добавлено в версии 3.6.
Изменено в версии 3.9: Если все веса равны нулю, вызывается исключение
ValueError.
-
random.shuffle(x) -
Перемешать последовательность x на месте.
Чтобы перемешать неизменяемую последовательность и вернуть новый перемешанный список, используйте вместо этого
sample(x, k=len(x)).Обратите внимание: даже для небольших значений
len(x)общее число перестановок x может быстро превысить период большинства генераторов случайных чисел. Это означает, что многие перестановки длинной последовательности невозможно сгенерировать. Например, последовательность длиной 2080 — самая длинная последовательность, которая помещается в период генератора случайных чисел «вихрь Мерсенна».Изменено в версии 3.11: Удалён необязательный параметр random.
-
random.sample(population, k, *, counts=None) -
Вернуть список длины k из уникальных элементов, выбранных из последовательности population. Используется для случайной выборки без возвращения.
Возвращает новый список с элементами из исходной совокупности, не изменяя её. Элементы результирующего списка расположены в порядке выбора, поэтому любые его срезы также будут допустимыми случайными выборками. Это позволяет разделить победителей розыгрыша (выборку) на обладателей главного и вторых призов (срезы).
Элементы совокупности не обязаны быть хешируемыми или уникальными. Если в совокупности есть повторы, каждый экземпляр может быть выбран в выборку.
Повторяющиеся элементы можно указывать по одному или с помощью необязательного именованного параметра только для ключевых слов counts. Например,
sample(['red', 'blue'], counts=[4, 2], k=5)эквивалентноsample(['red', 'red', 'red', 'red', 'blue', 'blue'], k=5).Чтобы выбрать случайную выборку из диапазона целых чисел, передайте в качестве аргумента объект
range(). Такой способ особенно быстр и экономичен по памяти при выборке из большой совокупности:sample(range(10000000), k=60).Если размер выборки превышает размер совокупности, вызывается исключение
ValueError.Изменено в версии 3.9: Добавлен параметр counts.
Изменено в версии 3.11: population должна быть последовательностью. Автоматическое преобразование множеств в списки больше не поддерживается.
Дискретные распределения
Следующая функция генерирует дискретное распределение.
-
random.binomialvariate(n=1, p=0.5) -
Биномиальное распределение. Возвращает число успехов в n независимых испытаниях, вероятность успеха в каждом из которых равна p:
Математически эквивалентно:
sum(random() < p for i in range(n))
Число испытаний n должно быть неотрицательным целым числом. Вероятность успеха p должна находиться в диапазоне
0.0 <= p <= 1.0. Результат — целое число в диапазоне0 <= X <= n.Добавлено в версии 3.12.
Распределения вещественных значений
Следующие функции генерируют конкретные распределения вещественных значений. Параметры функций названы в соответствии с переменными в уравнениях соответствующих распределений, как это принято в математике; большинство этих уравнений можно найти в любом учебнике по статистике.
-
random.random() -
Вернуть следующее случайное число с плавающей точкой в диапазоне
0.0 <= X < 1.0
-
random.uniform(a, b) -
Вернуть случайное число с плавающей точкой N, такое что
a <= N <= bприa <= bиb <= N <= aприb < a.Конечное значение
bможет входить или не входить в диапазон в зависимости от округления с плавающей точкой в выраженииa + (b-a) * random().
-
random.triangular(low, high, mode) -
Вернуть случайное число с плавающей точкой N, такое что
low <= N <= high, а также с заданным значением mode между этими границами. По умолчанию нижняя и верхняя границы low и high равны нулю и единице. По умолчанию аргумент mode равен середине между границами, что задаёт симметричное распределение.
-
random.betavariate(alpha, beta) -
Бета-распределение. Условия для параметров:
alpha > 0иbeta > 0. Возвращаемые значения находятся в диапазоне от 0 до 1.
-
random.expovariate(lambd=1.0) -
Экспоненциальное распределение. lambd — величина, обратная желаемому среднему значению. Она должна быть ненулевой. (Параметр назывался бы «lambda», но это зарезервированное слово в Python.) Если lambd положительно, возвращаемые значения находятся в диапазоне от 0 до плюс бесконечности; если отрицательно — от минус бесконечности до 0.
Изменено в версии 3.12: Добавлено значение по умолчанию для
lambd.
-
random.gammavariate(alpha, beta) -
Гамма-распределение. (Не гамма-функция!) Параметры формы и масштаба alpha и beta должны быть положительными. (Соглашения о вызовах различаются, и в некоторых источниках параметр «beta» определяется как величина, обратная масштабу.)
Функция плотности вероятности:
x ** (alpha - 1) * math.exp(-x / beta) pdf(x) = -------------------------------------- math.gamma(alpha) * beta ** alpha
-
random.gauss(mu=0.0, sigma=1.0) -
Нормальное распределение, также называемое гауссовским. mu — математическое ожидание, а sigma — стандартное отклонение. Эта функция немного быстрее, чем описанная ниже функция
normalvariate().Примечание о многопоточности: если два потока одновременно вызывают эту функцию, они могут получить одинаковое возвращаемое значение. Этого можно избежать тремя способами. 1) Использовать в каждом потоке отдельный экземпляр генератора случайных чисел. 2) Обернуть все вызовы блокировками. 3) Вместо неё использовать более медленную, но потокобезопасную функцию
normalvariate().Изменено в версии 3.11: Для mu и sigma теперь заданы значения аргументов по умолчанию.
-
random.lognormvariate(mu, sigma) -
Логнормальное распределение. Если взять натуральный логарифм от этого распределения, получится нормальное распределение с математическим ожиданием mu и стандартным отклонением sigma. mu может иметь любое значение, а sigma должно быть больше нуля.
-
random.normalvariate(mu=0.0, sigma=1.0) -
Нормальное распределение. mu — математическое ожидание, а sigma — стандартное отклонение.
Изменено в версии 3.11: Для mu и sigma теперь заданы значения аргументов по умолчанию.
-
random.vonmisesvariate(mu, kappa) -
mu — средний угол, выраженный в радианах в диапазоне от 0 до 2*pi, а kappa — параметр концентрации, который должен быть больше или равен нулю. Если kappa равен нулю, это распределение сводится к равномерному распределению случайных углов в диапазоне от 0 до 2*pi.
-
random.paretovariate(alpha) -
Распределение Парето. alpha — параметр формы.
-
random.weibullvariate(alpha, beta) -
Распределение Вейбулла. alpha — параметр масштаба, а beta — параметр формы.
Альтернативный генератор
-
class random.Random([seed]) -
Класс, реализующий используемый по умолчанию генератор псевдослучайных чисел модуля
random.Изменено в версии 3.11: Ранее seed мог быть любым хешируемым объектом. Теперь допустимы только следующие типы:
None,int,float,str,bytesилиbytearray.Если подклассы
Randomдолжны использовать другой базовый генератор, им следует переопределить следующие методы:-
seed(a=None, version=2) -
Переопределите этот метод в подклассах, чтобы настроить поведение
seed()для экземпляровRandom.
-
getstate() -
Переопределите этот метод в подклассах, чтобы настроить поведение
getstate()для экземпляровRandom.
-
setstate(state) -
Переопределите этот метод в подклассах, чтобы настроить поведение
setstate()для экземпляровRandom.
-
random() -
Переопределите этот метод в подклассах, чтобы настроить поведение
random()для экземпляровRandom.
При необходимости подкласс пользовательского генератора также может реализовать следующий метод:
-
getrandbits(k) -
Переопределите этот метод в подклассах, чтобы настроить поведение
getrandbits()для экземпляровRandom.
-
randbytes(n) -
Переопределите этот метод в подклассах, чтобы настроить поведение
randbytes()для экземпляровRandom.
-
-
class random.SystemRandom([seed]) -
Класс, использующий функцию
os.urandom()для генерации случайных чисел из источников, предоставляемых операционной системой. Доступен не во всех системах. Не зависит от программного состояния, поэтому последовательности нельзя воспроизвести. По этой причине методseed()не влияет на результат и игнорируется. При вызове методыgetstate()иsetstate()вызывают исключениеNotImplementedError.
Примечания о воспроизводимости
Иногда бывает полезно воспроизводить последовательности, выдаваемые генератором псевдослучайных чисел. Повторное использование начального значения должно обеспечивать воспроизводимость одной и той же последовательности при каждом запуске, если одновременно не выполняются несколько потоков.
Большинство алгоритмов модуля random и функций задания начального значения могут меняться в разных версиях Python, однако гарантируется неизменность двух аспектов:
- Если будет добавлен новый метод задания начального значения, будет предоставлен совместимый с предыдущими версиями метод.
- Метод
random()генератора будет и далее выдавать ту же последовательность, если совместимый метод задания начального значения получит то же значение.
Примеры
Базовые примеры:
>>> random() # Random float: 0.0 <= x < 1.0 0.37444887175646646 >>> uniform(2.5, 10.0) # Random float: 2.5 <= x <= 10.0 3.1800146073117523 >>> expovariate(1 / 5) # Interval between arrivals averaging 5 seconds 5.148957571865031 >>> randrange(10) # Integer from 0 to 9 inclusive 7 >>> randrange(0, 101, 2) # Even integer from 0 to 100 inclusive 26 >>> choice(['win', 'lose', 'draw']) # Single random element from a sequence 'draw' >>> deck = 'ace two three four'.split() >>> shuffle(deck) # Shuffle a list >>> deck ['four', 'two', 'ace', 'three'] >>> sample([10, 20, 30, 40, 50], k=4) # Four samples without replacement [40, 10, 50, 30]
Моделирование:
>>> # Six roulette wheel spins (weighted sampling with replacement)
>>> choices(['red', 'black', 'green'], [18, 18, 2], k=6)
['red', 'green', 'black', 'black', 'red', 'black']
>>> # Deal 20 cards without replacement from a deck
>>> # of 52 playing cards, and determine the proportion of cards
>>> # with a ten-value: ten, jack, queen, or king.
>>> deal = sample(['tens', 'low cards'], counts=[16, 36], k=20)
>>> deal.count('tens') / 20
0.15
>>> # Estimate the probability of getting 5 or more heads from 7 spins
>>> # of a biased coin that settles on heads 60% of the time.
>>> sum(binomialvariate(n=7, p=0.6) >= 5 for i in range(10_000)) / 10_000
0.4169
>>> # Probability of the median of 5 samples being in middle two quartiles
>>> def trial():
... return 2_500 <= sorted(choices(range(10_000), k=5))[2] < 7_500
...
>>> sum(trial() for i in range(10_000)) / 10_000
0.7958
Пример статистического бутстрепа с использованием повторной выборки с возвращением для оценки доверительного интервала среднего значения выборки:
# https://www.thoughtco.com/example-of-bootstrapping-3126155
from statistics import fmean as mean
from random import choices
data = [41, 50, 29, 37, 81, 30, 73, 63, 20, 35, 68, 22, 60, 31, 95]
means = sorted(mean(choices(data, k=len(data))) for i in range(100))
print(f'The sample mean of {mean(data):.1f} has a 90% confidence '
f'interval from {means[5]:.1f} to {means[94]:.1f}')
Пример перестановочного теста с повторной выборкой для определения статистической значимости или p-значения наблюдаемой разницы между эффектами препарата и плацебо:
# Example from "Statistics is Easy" by Dennis Shasha and Manda Wilson
from statistics import fmean as mean
from random import shuffle
drug = [54, 73, 53, 70, 73, 68, 52, 65, 65]
placebo = [54, 51, 58, 44, 55, 52, 42, 47, 58, 46]
observed_diff = mean(drug) - mean(placebo)
n = 10_000
count = 0
combined = drug + placebo
for i in range(n):
shuffle(combined)
new_diff = mean(combined[:len(drug)]) - mean(combined[len(drug):])
count += (new_diff >= observed_diff)
print(f'{n} label reshufflings produced only {count} instances with a difference')
print(f'at least as extreme as the observed difference of {observed_diff:.1f}.')
print(f'The one-sided p-value of {count / n:.4f} leads us to reject the null')
print(f'hypothesis that there is no difference between the drug and the placebo.')
Моделирование времени прибытия и обслуживания для многоканальной очереди:
from heapq import heapify, heapreplace
from random import expovariate, gauss
from statistics import mean, quantiles
average_arrival_interval = 5.6
average_service_time = 15.0
stdev_service_time = 3.5
num_servers = 3
waits = []
arrival_time = 0.0
servers = [0.0] * num_servers # time when each server becomes available
heapify(servers)
for i in range(1_000_000):
arrival_time += expovariate(1.0 / average_arrival_interval)
next_server_available = servers[0]
wait = max(0.0, next_server_available - arrival_time)
waits.append(wait)
service_duration = max(0.0, gauss(average_service_time, stdev_service_time))
service_completed = arrival_time + wait + service_duration
heapreplace(servers, service_completed)
print(f'Mean wait: {mean(waits):.1f} Max wait: {max(waits):.1f}')
print('Quartiles:', [round(q, 1) for q in quantiles(waits)])
См. также
Статистика для хакеров — видеоурок Джейка Вандерпласа по статистическому анализу с использованием нескольких фундаментальных понятий, включая моделирование, выборку, перемешивание и перекрёстную проверку.
Экономическое моделирование — модель рынка, созданная Питером Норвигом, демонстрирующая эффективное использование многих инструментов и распределений этого модуля (gauss, uniform, sample, betavariate, choice, triangular и randrange).
Практическое введение в теорию вероятностей (на Python) — руководство Питера Норвига, посвящённое основам теории вероятностей, написанию моделей и анализу данных с помощью Python.
Рецепты
Эти рецепты показывают, как эффективно делать случайный выбор из комбинаторных итераторов модуля itertools:
def random_product(*args, repeat=1):
"Random selection from itertools.product(*args, **kwds)"
pools = [tuple(pool) for pool in args] * repeat
return tuple(map(random.choice, pools))
def random_permutation(iterable, r=None):
"Random selection from itertools.permutations(iterable, r)"
pool = tuple(iterable)
r = len(pool) if r is None else r
return tuple(random.sample(pool, r))
def random_combination(iterable, r):
"Random selection from itertools.combinations(iterable, r)"
pool = tuple(iterable)
n = len(pool)
indices = sorted(random.sample(range(n), r))
return tuple(pool[i] for i in indices)
def random_combination_with_replacement(iterable, r):
"Choose r elements with replacement. Order the result to match the iterable."
# Result will be in set(itertools.combinations_with_replacement(iterable, r)).
pool = tuple(iterable)
n = len(pool)
indices = sorted(random.choices(range(n), k=r))
return tuple(pool[i] for i in indices)
По умолчанию random() возвращает числа, кратные 2⁻⁵³, в диапазоне 0.0 ≤ x < 1.0. Все такие числа равномерно распределены и точно представимы в виде чисел с плавающей точкой Python. Однако многие другие представимые числа с плавающей точкой в этом интервале не могут быть выбраны. Например, 0.05954861408025609 не является целым кратным 2⁻⁵³.
В следующем рецепте используется другой подход. Возможен выбор любого числа с плавающей точкой из интервала. Мантисса берётся из равномерного распределения целых чисел в диапазоне 2⁵² ≤ mantissa < 2⁵³. Показатель берётся из геометрического распределения, в котором показатели меньше -53 встречаются вдвое реже, чем следующий больший показатель.
from random import Random
from math import ldexp
class FullRandom(Random):
def random(self):
mantissa = 0x10_0000_0000_0000 | self.getrandbits(52)
exponent = -53
x = 0
while not x:
x = self.getrandbits(32)
exponent += x.bit_length() - 32
return ldexp(mantissa, exponent)
Все распределения вещественных значений в классе будут использовать новый метод:
>>> fr = FullRandom() >>> fr.random() 0.05954861408025609 >>> fr.expovariate(0.25) 8.87925541791544
Рецепт концептуально эквивалентен алгоритму, который выбирает числа из всех кратных 2⁻¹⁰⁷⁴ в диапазоне 0.0 ≤ x < 1.0. Все такие числа равномерно распределены, но большинство из них приходится округлять вниз до ближайшего представимого числа с плавающей точкой Python. (Значение 2⁻¹⁰⁷⁴ — это наименьшее положительное ненормализованное число с плавающей точкой, равное math.ulp(0.0).)
См. также
Генерация псевдослучайных чисел с плавающей точкой — статья Аллена Б. Дауни, в которой описаны способы генерировать числа с плавающей точкой с большей точностью, чем обычно генерирует random().
Использование командной строки
Добавлено в версии 3.13.
Модуль random можно запускать из командной строки.
python -m random [-h] [-c CHOICE [CHOICE ...] | -i N | -f N] [input ...]
Поддерживаются следующие параметры:
-
-h, --help -
Вывести справку и завершить работу.
-
-c CHOICE [CHOICE ...] -
--choice CHOICE [CHOICE ...] -
Вывести случайный элемент с помощью
choice().
-
-i <N> -
--integer <N> -
Вывести случайное целое число от 1 до N включительно с помощью
randint().
-
-f <N> -
--float <N> -
Вывести случайное число с плавающей точкой от 0 до N включительно с помощью
uniform().
Если параметры не указаны, результат зависит от входных данных:
Пример использования командной строки
Вот несколько примеров интерфейса командной строки random:
$ # Choose one at random $ python -m random egg bacon sausage spam "Lobster Thermidor aux crevettes with a Mornay sauce" Lobster Thermidor aux crevettes with a Mornay sauce $ # Random integer $ python -m random 6 6 $ # Random floating-point number $ python -m random 1.8 1.7080016272295635 $ # With explicit arguments $ python -m random --choice egg bacon sausage spam "Lobster Thermidor aux crevettes with a Mornay sauce" egg $ python -m random --integer 6 3 $ python -m random --float 1.8 1.5666339105010318 $ python -m random --integer 6 5 $ python -m random --float 6 3.1942323316565915
© 2001–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/random.html