Django-Admin.ru

Модуль random в Python

Модуль random в Python: случайное число через randint и random, выбор из списка choice, choices и sample, shuffle, seed и модуль secrets для паролей.

Редакция Django-Admin.ru
· обновлено · 8 мин чтения

Содержание · 9 разделов
  1. Как получить случайное число
  2. Случайный выбор из списка: choice, choices, sample
  3. Перемешать список: shuffle
  4. seed: воспроизводимые случайные числа
  5. Отдельный генератор: random.Random
  6. Распределения: gauss и другие
  7. Пароли и токены: модуль secrets вместо random
  8. Частые ошибки
  9. shuffle вернул None
  10. Не та граница диапазона
  11. AttributeError: partially initialized module ‘random’
  12. Выбор из пустого списка или множества
  13. Вещественные границы в randint
  14. Частые вопросы
  15. Как создать список случайных чисел?
  16. Как получить случайное число из заданного количества цифр?
  17. Как выполнить действие с заданной вероятностью?
  18. Как сгенерировать случайную дату?
  19. Почему random выдаёт одинаковые числа при каждом запуске?
  20. Итог

Модуль random из стандартной библиотеки Python генерирует псевдослучайные числа и выбирает случайные элементы. Короткий ответ: random.randint(1, 6) возвращает целое число от 1 до 6 включительно, random.choice(items) — случайный элемент списка, а random.shuffle(items) перемешивает список на месте.

Ниже — все основные функции модуля, воспроизводимые результаты через seed(), частые ошибки и главное предупреждение: для паролей, токенов и кодов подтверждения random не подходит, нужен модуль secrets. Примеры проверены на Python 3.12, вывод показан комментарием # →.

Как получить случайное число

import random

print(random.randint(1, 6))  # → число от 1 до 6, при каждом запуске разное

Результаты random меняются от запуска к запуску. Чтобы примеры в статье давали ровно тот вывод, что показан в комментариях, в начале каждого блока вызывается random.seed() — о нём подробно ниже.

import random

random.seed(42)
print(random.random())               # → 0.6394267984578837
print(random.uniform(1.5, 2.5))      # → 1.525010755222667
print(random.randint(1, 6))          # → 3
print(random.randrange(0, 100, 10))  # → 30
ФункцияЧто возвращает
random()float в диапазоне от 0.0 включительно до 1.0 не включая
uniform(a, b)float между a и b
randint(a, b)int от a до b, обе границы включены
randrange(stop)int от 0 до stop, не включая stop
randrange(start, stop, step)int из range(start, stop, step)

randint(a, b) — это то же, что randrange(a, b + 1). Логика randrange такая же, как у функции range: верхняя граница не входит, можно задать шаг. В примере выше randrange(0, 100, 10) выбирает из чисел 0, 10, 20 … 90.

Случайный выбор из списка: choice, choices, sample

import random

random.seed(10)
colors = ["красный", "зелёный", "синий"]

print(random.choice(colors))        # → синий
print(random.choices(colors, k=5))
# → ['красный', 'зелёный', 'красный', 'зелёный', 'зелёный']
print(random.choices(["выигрыш", "проигрыш"], weights=[1, 9], k=5))
# → ['проигрыш', 'проигрыш', 'выигрыш', 'проигрыш', 'выигрыш']
print(random.sample(range(1, 50), k=6))  # → [48, 24, 3, 27, 9, 39]
  • choice(seq) — один случайный элемент.
  • choices(seq, k=n) — n элементов с повторениями: один элемент может выпасть несколько раз. Параметр weights задаёт относительные веса: в примере «проигрыш» в среднем выпадает в 9 раз чаще, хотя на коротком отрезке пропорция заметно отклоняется.
  • sample(seq, k=n) — n разных элементов без повторений, как при вытягивании шаров из лотерейного барабана.

Все три функции работают с любой последовательностью: списком, кортежем, строкой, range. Для множества или словаря сначала получите список — например, sorted(my_set).

Перемешать список: shuffle

shuffle() перемешивает список на месте и возвращает None:

import random

random.seed(10)
cards = ["A", "K", "Q", "J", "10"]
print(random.shuffle(cards))  # → None
print(cards)                  # → ['J', 'Q', 'K', 'A', '10']

Если исходный список нужно сохранить, получите перемешанную копию через sample() с k, равным длине списка:

random.seed(5)
nums = [1, 2, 3, 4, 5]
mixed = random.sample(nums, k=len(nums))
print(mixed, nums)  # → [5, 3, 4, 2, 1] [1, 2, 3, 4, 5]

shuffle() не работает с кортежами и строками — они неизменяемы. Подробнее о списках и их методах — в статье о списках в Python.

seed: воспроизводимые случайные числа

Генератор в модуле random — псевдослучайный: числа вычисляются по алгоритму (Mersenne Twister) из начального значения — зерна. Без явного seed() зерно берётся из источника случайности операционной системы или текущего времени, поэтому каждый запуск даёт новые числа. С одинаковым зерном последовательность повторяется:

import random

random.seed(42)
print([random.randint(1, 100) for _ in range(5)])  # → [82, 15, 4, 95, 36]
random.seed(42)
print([random.randint(1, 100) for _ in range(5)])  # → [82, 15, 4, 95, 36]

Фиксированное зерно нужно в тестах, при отладке, в научных расчётах и играх с «сидом» карты. Повторяемость между версиями Python гарантирована только для random(), а результат randint(), choice() и других функций при том же зерне в будущих версиях может измениться.

Отдельный генератор: random.Random

Функции модуля используют один общий генератор, и вызов random.seed() в одном месте программы влияет на все остальные. Если нужна изолированная воспроизводимая последовательность, создайте свой экземпляр:

import random

rng = random.Random(7)
print(rng.randint(1, 100), rng.choice("abc"))  # → 42 a

У экземпляра те же методы, что у модуля: rng.shuffle(), rng.sample() и т. д.

Распределения: gauss и другие

Кроме равномерного распределения модуль умеет генерировать числа по другим законам. Самое востребованное — нормальное распределение:

import random

random.seed(1)
print(round(random.gauss(170, 10), 1))  # → 182.9 — «рост» со средним 170 и отклонением 10

Есть также normalvariate(), expovariate(), triangular(), betavariate() и другие — полный список в документации модуля random. Если нужно сгенерировать миллионы чисел или целые массивы, быстрее работает numpy.random — подробнее в статье о NumPy.

Пароли и токены: модуль secrets вместо random

Важно: не используйте random для паролей, токенов сброса, кодов подтверждения и всего, что связано с безопасностью. Mersenne Twister предсказуем: по достаточному количеству выданных значений можно восстановить состояние генератора и вычислить следующие числа.

Для таких задач в стандартной библиотеке есть модуль secrets (Python 3.6+). Он берёт случайность из криптографически стойкого источника операционной системы:

import secrets
import string

print(secrets.token_hex(16))      # → например, 4203a28fb1de86b0d0f5dda434db86aa (32 символа)
print(secrets.token_urlsafe(16))  # → например, 19QB2uax4TfiNXdPkIKTbg — для ссылок
print(secrets.randbelow(10))      # → целое от 0 до 9

alphabet = string.ascii_letters + string.digits
password = "".join(secrets.choice(alphabet) for _ in range(12))
print(password)                   # → например, rTneK9Wcsvhw

code = f"{secrets.randbelow(10**6):06d}"
print(code)                       # → например, 055220 — шестизначный код из SMS

Вывод здесь при каждом запуске новый, и задать для secrets зерно нельзя — в этом и смысл. Аргумент token_hex() и token_urlsafe() — количество случайных байтов, а не символов: 16 байтов дают 32 шестнадцатеричных символа. Склейку строки из символов через генератор подробнее разбирает статья о методе join.

Частые ошибки

shuffle вернул None

cards = random.shuffle([1, 2, 3])
print(cards)  # → None

shuffle() меняет переданный список и ничего не возвращает. Перемешайте список отдельной строкой и дальше работайте с ним, а для копии используйте random.sample(items, k=len(items)).

Не та граница диапазона

randint(1, 10) может вернуть 10, а randrange(1, 10) — нет. Если в игре «кубик» иногда не выпадает шестёрка или, наоборот, выпадает лишнее значение, проверьте, какую функцию вы вызвали.

AttributeError: partially initialized module ‘random’

Файл скрипта назван random.py. Python импортирует его вместо стандартного модуля:

AttributeError: partially initialized module 'random' has no attribute 'randint' (most likely due to a circular import)

С Python 3.13 сообщение прямо подсказывает причину: module 'random' has no attribute 'randint' (consider renaming '…random.py' since it has the same name as the standard library module named 'random' …).

Переименуйте файл, например в dice.py, и удалите папку __pycache__ рядом с ним, если она появилась. Та же проблема возникает с файлами json.py, datetime.py, string.py и другими именами модулей стандартной библиотеки.

Выбор из пустого списка или множества

random.choice([])
# → IndexError: Cannot choose from an empty sequence
random.sample({1, 2, 3}, 2)
# → TypeError: Population must be a sequence.  For dicts or sets, use sorted(d).
random.sample([1, 2], 3)
# → ValueError: Sample larger than population or is negative

Проверяйте, что последовательность не пуста и содержит не меньше k элементов, а множества преобразуйте в список. Такие ошибки удобно перехватывать через try/except.

Вещественные границы в randint

random.randint(1.5, 3) выбросит TypeError: 'float' object cannot be interpreted as an integer. Для дробных чисел используйте uniform().

Частые вопросы

Как создать список случайных чисел?

Генератор списка с randint() даёт числа с возможными повторами, sample() — без повторов:

import random

random.seed(3)
print([random.randint(1, 100) for _ in range(10)])
# → [31, 76, 70, 17, 48, 78, 61, 81, 75, 9]
print(random.sample(range(1, 101), k=10))  # 10 разных чисел от 1 до 100

Как получить случайное число из заданного количества цифр?

Задайте границы через степени десяти: наименьшее четырёхзначное число — 10 ** 3, наибольшее — 10 ** 4 - 1:

n = 4
print(random.randint(10 ** (n - 1), 10 ** n - 1))  # → например, 4898

Для кодов, где допустимы ведущие нули, как в SMS, используйте secrets и форматирование :06d из раздела выше.

Как выполнить действие с заданной вероятностью?

Сравните random.random() с вероятностью: условие random.random() < 0.3 выполняется примерно в 30 % случаев:

if random.random() < 0.3:
    print("бонус выпал")

Как сгенерировать случайную дату?

Выберите случайное число дней внутри диапазона и прибавьте его к начальной дате через timedelta:

import random
from datetime import date, timedelta

start, end = date(2026, 1, 1), date(2026, 12, 31)
day = start + timedelta(days=random.randint(0, (end - start).days))
print(day)  # → например, 2026-05-02

Подробнее об арифметике дат — в статье о datetime в Python.

Почему random выдаёт одинаковые числа при каждом запуске?

Где-то в программе зерно задано константой: random.seed(42) в вашем коде, в импортированном модуле или в настройках тестов. Уберите вызов или используйте отдельный генератор random.Random() для участка, которому нужна воспроизводимость. Вызов random.seed() без аргументов снова берёт зерно из источника случайности системы.

Итог

Для случайных чисел берите randint() (границы включены) или random(), для выбора из списка — choice(), choices() и sample(), для перемешивания — shuffle(), который меняет список на месте. seed() делает результат воспроизводимым, а для паролей и токенов нужен только secrets. Другие конструкции языка и модули стандартной библиотеки собраны в шпаргалке по синтаксису Python, а закрепить материал помогут задачи по Python.

  • #Python
  • #random
  • #secrets
  • #Случайные числа
  • #Стандартная библиотека
↑ ↓ выборEnter открытьEsc закрыть