Модуль random в Python
Модуль random в Python: случайное число через randint и random, выбор из списка choice, choices и sample, shuffle, seed и модуль secrets для паролей.
Содержание · 9 разделов
- Как получить случайное число
- Случайный выбор из списка: choice, choices, sample
- Перемешать список: shuffle
- seed: воспроизводимые случайные числа
- Отдельный генератор: random.Random
- Распределения: gauss и другие
- Пароли и токены: модуль secrets вместо random
- Частые ошибки
- shuffle вернул None
- Не та граница диапазона
- AttributeError: partially initialized module ‘random’
- Выбор из пустого списка или множества
- Вещественные границы в randint
- Частые вопросы
- Как создать список случайных чисел?
- Как получить случайное число из заданного количества цифр?
- Как выполнить действие с заданной вероятностью?
- Как сгенерировать случайную дату?
- Почему random выдаёт одинаковые числа при каждом запуске?
- Итог
Модуль 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
- #Случайные числа
- #Стандартная библиотека