Python. Генерация псевдослучайных чисел. Модуль random

Скрипты выполнялись под Python версии 2.7.9.

Генерация случайных чисел используется для:

  • создания идентификаторов сессий,
  • создания токенов (CSRF и т.п.),
  • создания произвольных паролей и кодов доступа,
  • создания произвольных последовательностей данных в играх,
  • создания уникальных номеров для маркетинговых акций (подарочные карты, розыгрыш призов по коду и т.п.).

В Python существует несколько основных модулей и классов, связанных с генерацией псевдослучайных чисел:

  • _random - реализует алгоритм Mersenne Twister, написан на языке C;
  • класс Random - наследует _random, написан на языке Python;
  • модуль os - предоставляет доступ к внешнему источнику случайных чисел, в случае Linux - это /dev/urandom;
  • класс SystemRandom наследует Random, но для генерации случайных чисел обращается к os.urandom;
  • класс WichmannHill наследует Random, реализует алгоритм Вихмана-Хилла для генерации псевдослучайных чисел.

В качестве основного генератора псевдослучайных чисел Python использует Mersenne Twister, доступ к которому предоставляет класс Random. Mersenne Twister имеет период 2 ** 19937-1. Это один из наиболее протестированных генераторов случайных чисел. Основная часть реализована на C. К сожалению, не подходит для криптографических задач.

В целях криптографической безопасности рекомендуется использовать класс SystemRandom и функцию os.urandom().

Mersenne Twister заменил ранее используемый алгоритм WichmannHill. WichmannHill не соответствует современным требованиям безопасности.

Модуль random

Найти файл модуля:

И посмотреть содержимое модуля (для особо любопытных):

Прежде чем использовать модуль, необходимо подключить его с помощью инструкции:

Функции модуля random, генерирующие вещественнозначное распределение

Следующие функции генерируют конкретные вещественнозначные распределения.

random.random()

Функция random() возвращает псевдослучайное число с плавающей точкой в диапазоне от 0.0 до 1.0.

Если необходимо получить число из большего диапазона, например, от 0 до 10, можно умножить результат функции на 10.

random.uniform(start, stop)

Функция uniform() возвращает псевдослучайное вещественное число в указанном диапазоне от start до stop включительно.

random.triangular(low, high, mode)

Функция triangular() — возвращает псевдослучайное число N с плавающей точкой: low <= N <= high. По умолчанию нижняя и верхняя границы диапазона равны нулю и единице.

Параметр mode по умолчанию задает среднюю точку между указанными границами, предоставляя симметричное распределение:

Отобразить результаты triangular() на графике:

Графическое представление результатов random.triangular() в Python

Графическое представление результатов random.triangular() в Python

Функция triangular() появилась в Python 2.6.

random.betavariate(alpha, beta)

Функция betavariate() — бета-распределение. Условия по параметрам: alpha > 0 и beta > 0. Возвращает значения от 0 до 1.

random.expovariate(lambd)

Функция expovariate() — экспоненциальное распределение. lambd равен 1.0, деленное на желаемое среднее значение. Lambd не должен быть равен нулю. Возвращаемые значения от 0 до плюс бесконечности, если lambd положительно, и от минус бесконечности до 0, если lambd отрицательный.

Показать результаты expovariate() графически:

Графическое представление результатов random.expovariate() в Python

Графическое представление результатов random.expovariate() в Python

random.gammavariate(alpha, beta)

Гамма-распределение. Условия по параметрам: alpha > 0 и beta > 0.

random.gauss(mu, sigma)

gauss() — Гауссовское распределение. mu - среднее значение, а sigma - стандартное отклонение. Работает быстрее, чем normalvariate().

random.lognormvariate(mu, sigma)

lognormvariate() — логнормальное распределение. Если вы возьмете натуральный логарифм этого распределения, вы получите нормальное распределение со средней сигмой mu и стандартным
отклонением. mu может иметь любое значение, а sigma должна быть больше нуля.

random.normalvariate(mu, sigma)

normalvariate() — нормальное распределение. 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 - параметр формы.

Функции модуля random для работы с целыми числами

random.randrange(start, stop[, step])

Функция random.randrange() - возвращает случайно выбранное целое число из строго заданного диапазона значений. Функция может принимать от одного до трех аргументов.

  • randrange(stop) - случайное число будет выбираться из диапазона значений от нуля до числа stop.
  • randrange(start, stop) - диапазон возможных значений от числа start до числа stop.
  • randrange(start, stop, step) - выборка случайного целого числа происходит от числа start до числа stop с шагом step.

Пример:

Функция появилась в Python 1.5.2.

Результат вызова randrange(start, stop, step) эквивалентен вызову функции choice(range(start, stop, step)).

random.randint(min, max)

Функция randint(min, max) возвращает случайное целое число в интервале от min до max.

Функции модуля random для последовательностей

random.shuffle(seq[, random])

Для работы со списками в модуле random определены две функции: shuffle() и choice().
Функция shuffle() перемешивает список случайным образом, а функция choice() возвращает один случайный элемент из списка.

При перемешивании изменяется сам список, поэтому функция работает только с изменяемыми и упорядоченными (индексируемыми) типами данных.

  • seq - список, подлежащий взбалтыванию,
  • random - необязательный аргумент, функция, возвращающая случайный float в интервале от 0.0 до 1.0. По умолчанию используется функция random().

Пример:

Указываем вместо random(), используемую по умолчанию, иную функцию. Тут приведен примитивнейший вариант, просто для примера:

random.choice(seq)

Функция choice() - возвращает случайный элемент из любой непустой последовательности (строка, кортеж, список). Только упорядоченные (индексируемые) последовательности.

Если последовательность окажется пустой, будет инициирована IndexError.

random.sample(population, k)

Функция sample() возвращает список длиной k, созданный с помощью произвольной выборки элементов из последовательности population. Работает с кортежами, списками, множествами, словарями, строками.

Функция добавлена в Python 2.3.

Прочие функции модуля random

random.seed()

Функция seed() - инициализация генератора случайных чисел, настройка на новую последовательность.

Данная функция имеет особое значение, когда генератор случайных чисел используется для обеспечения безопасности приложения, например, при генерации токенов, идентификаторов сессий. В некоторых фреймворках под Python инициализация генератора случайных чисел производится один раз, при запуске сервера. Вот тут-то и может пригодиться принудительный дополнительный вызов seed().

В версии Python 2.4 появились изменения, позволяющие использовать для генерации псевдослучайных чисел ресурсы операционной системы (см. os.urandom() ).

random.getstate()

Функция random.getstate() возвращает объект, фиксирующий текущее внутреннее состояние генератора. Этот объект может быть передан в setstate() для восстановления состояния.

Немного бессмысленная демонстрация возвращаемого содержимого, но все-таки:

Функция появилась в Python 2.1.

random.setstate(state)

random.setstate(state) - восстанавливает внутреннее состояние генератора. Параметр state - объект, предварительно порожденный функцией getstate().

Функция появилась в Python 2.1.

Восстановление состояния приводит вот к таким эффектам:

random.jumpahead(n)

Функция появилась в Python 2.1. В основном полезна для многопоточных программ. Изменение внутреннего состояния генератора.

random.getrandbits(k)

getrandbits(k) - возвращает значение типа long int с k случайными битами.

Поставляется с генератором MersenneTwister. Некоторые другие генераторы также могут предоставлять getrandbits() как необязательную часть API.

Реализованный getrandbits() позволяет randrange() обрабатывать сколь угодно большие диапазоны.

Функция была добавлена в Python 2.4.

Альтернативные генераторы

При необходимости вы можете создать собственный подкласс класса random и реализовать собственный генератор случайных данных.

В этом случае вам потребуется переопределить методы: random(), seed(), getstate(), setstate() и jumpahead().

Если в новом генераторе будет предоставляться метод getrandbits(), метод randrange() сможет выполнять выборку по значительно большему диапазону.

class random.WichmannHill([seed])

class random.WichmannHill([seed]) - класс, который реализует алгоритм Вихмана-Хилла в качестве генератора случайных чисел.

Имеет все те же методы, что и класс random, и дополнительно метод whseed(). Данный класс плохо подходит для работы с потоками.

Период генератора равен 6 953 607 871 644 - это слишком мало и может привести к перекрытию между двумя случайными последовательностями.

Ранние версии Python использовали именно этот генератор в качестве основного. В Python 2.3 алгоритм MersenneTwister заменил Wichmann-Hill в качестве генератора по умолчанию.

class random.SystemRandom([seed])

Класс, который использует системную функцию os.urandom() для генерации случайных чисел из источников, предоставляемых операционной системой. Доступен не для всех систем.

Не полагается на состояние программного обеспечения, последовательности не воспроизводятся. Методы seed() и jumpahead() не действуют и игнорируются. Попытка вызова методов getstate() и setstate() приводит к ошибке NotImplementedError.

Данная функциональность была добавлена в Python 2.4.

Еще один пример:

И еще один пример использования SystemRandom():

os.urandom(n)

Данная функция не относится к модулю random. Рассматриваю ее потому, что она часто упоминается при рассмотрении возможностей модуля random, и к тому же используется классом SystemRandom.

urandom(n) - возвращает строку из n случайных байт. Функция возвращает случайные байты из источника случайных чисел, специфичного для операционной системы. Качество возвращаемых данных зависит от реализации ОС. В UNIX-подобной системе будет вызываться /dev/urandom, в Windows - CryptGenRandom().

Если источник случайных данных не найден, генерируется ошибка NotImplementedError.

urandom(n) появился в Python 2.4. Подходит для использования в криптографии.

Примеры превращения выдаваемого urandom результата во что-то удобочитаемое и применимое:

Второй пример:

Третий пример, создаем CSRF токен:

Полезные ссылки

https://docs.python.org/2/library/random.html