Обзор библиотеки random: генерация случайных данных в коде Python

Раздел: Окружение -> Популярные библиотеки Python

Библиотека random в Python

Наиболее эффективное решение для ежедневных задач - использование random.randint и random.choice. Эти функции работают быстро и не требуют дополнительных настроек.

import random
# целое число от 1 до 10
num = random.randint(1, 10)
# случайный элемент списка
items = ['red', 'green', 'blue']
color = random.choice(items)
print(num, color)

библиотека random python (библиотека random в python)

Распространённая ошибка: передача нецелых аргументов в randint (вызовет TypeError). Для плавающих чисел используйте uniform. Также без seed каждый запуск даёт разные результаты - если требуется воспроизводимость, установите seed.

Как получить случайное число с плавающей точкой в произвольном интервале?

Функция random.uniform(a, b) возвращает равномерно распределённое float. Границы могут быть нецелыми.

import random
weight = random.uniform(50.0, 100.0)
print(weight)

Если a > b, значения автоматически меняются местами. Учтите, что uniform может вернуть значение, равное a или b, но из-за погрешностей это бывает редко.

Как перемешать список на месте?

Метод random.shuffle(list) изменяет исходный список, не возвращая нового.

import random
deck = list(range(52))
random.shuffle(deck)
print(deck[:5])

Shuffle работает in-place. Если нужно сохранить оригинал, создайте копию через deck_copy = deck[:] перед перемешиванием. Для неизменяемых последовательностей (кортежи) shuffle не работает - используйте random.sample.

Как выбрать несколько случайных элементов без повторений?

Функция random.sample(population, k) возвращает список из k уникальных элементов.

import random
students = ['Alice', 'Bob', 'Charlie', 'David', 'Eve']
winners = random.sample(students, 3)
print(winners)

Если k больше длины population, выбрасывается ValueError. Для выборки с возможными повторами используйте random.choices.

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

Функция random.gauss(mu, sigma) возвращает значение из нормального распределения с заданными средним mu и стандартным отклонением sigma.

import random
height = random.gauss(170, 10)
print(height)

gauss быстрее, чем normalvariate, но не подходит для многопоточных сред из-за глобального состояния? На самом деле обе используют один генератор. Для воспроизводимости задайте seed глобально или создайте свой экземпляр.

Как получить криптографически стойкие случайные числа?

Класс random.SystemRandom использует системные источники энтропии (например, /dev/urandom). Создаётся экземпляр, и его методы безопасны для паролей и токенов.

import random
sys_rand = random.SystemRandom()
token = sys_rand.randint(100000, 999999)
choice = sys_rand.choice(['a','b','c'])
print(token, choice)

SystemRandom медленнее обычного и не поддерживает seed (всегда истинно случайный). Используйте только когда стойкость критична.

Как создать собственный генератор с заданным начальным состоянием?

Класс random.Random(seed) позволяет изолировать генератор, не влияя на глобальное состояние модуля random.

import random
rng1 = random.Random(42)
rng2 = random.Random(42)
print(rng1.random(), rng2.random())  # одинаково
print(rng1.randint(1,10), rng2.randint(1,10)) # тоже одинаково

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

Расширенные примеры использования random

1. Генерация случайного пароля с взвешенными вероятностями

Использование random.choices с параметром weights позволяет задать вероятность выбора каждого символа.

Пример
import random
import string
# символы
letters = string.ascii_letters
digits = string.digits
symbols = '!@#$%^&*()_+-='
# веса: буквы 2, цифры 1, символы 3
weights = [2]*len(letters) + [1]*len(digits) + [3]*len(symbols)
chars = letters + digits + symbols
password = ''.join(random.choices(chars, weights=weights, k=16))
print(password)
Пример: "kD9@#aB!xYz7$Wq"

2. Симуляция подбрасывания монеты с эффективным получением битов

Функция random.getrandbits(n) генерирует n случайных битов пакетно, что быстрее чем по одному.

Пример
import random
# 1 миллион подбрасываний
flips = random.getrandbits(1_000_000)
ones = bin(flips).count('1')
zeros = 1_000_000 - ones
print(f'Орёл: {zeros}, Решка: {ones}')
Орёл: 499872, Решка: 500128

3. Изолированные генераторы в многопоточном приложении

Создание отдельных экземпляров random.Random для каждого потока предотвращает состояние гонки.

Пример
import random
import threading
def worker(rng):
    for _ in range(5):
        print(threading.current_thread().name, rng.randint(1,100))
# создаём два генератора с разными seed
rng_a = random.Random(123)
rng_b = random.Random(456)
t1 = threading.Thread(target=worker, args=(rng_a,), name='A')
t2 = threading.Thread(target=worker, args=(rng_b,), name='B')
t1.start()
t2.start()
t1.join()
t2.join()

4. Генерация случайной даты внутри диапазона

Перевод даты в количество дней и обратно позволяет легко получить случайную дату.

Пример
import random
from datetime import date, timedelta
start = date(2023, 1, 1)
end = date(2024, 12, 31)
days = (end - start).days
random_day = random.randint(0, days)
random_date = start + timedelta(days=random_day)
print(random_date)
2023-11-07

5. Имитация бросков игрального кубика с разными распределениями

Кубик с заданными вероятностями граней с помощью random.choices.

Пример
import random
# стороны кубика
sides = [1,2,3,4,5,6]
# веса: например, смещённый кубик
weights = [1,1,1,1,1,2]  # шестёрка выпадает вдвое чаще
throws = random.choices(sides, weights=weights, k=12)
print(throws)
[6, 2, 6, 4, 1, 6, 3, 5, 6, 2, 6, 1]

6. Использование random.randrange и random.sample для создания лотерейного билета

generate уникальные номера из диапазона.

Пример
import random
lottery_numbers = random.sample(range(1, 50), 6)
print(sorted(lottery_numbers))
[5, 12, 23, 34, 39, 47]

7. Задание seed для воспроизводимости в отладке

Фиксация состояния позволяет повторять одну и ту же последовательность.

Пример
import random
random.seed(42)
print([random.randint(1,100) for _ in range(5)])
# повторный запуск даст ту же последовательность
[82, 15, 4, 95, 36]

Библиотека random в Python - comments

En
библиотека random python (python)