Random.shuffle: примеры (PYTHON)
random.shuffle(x: mutable sequence, random: random.Random=None): NoneФункция random.shuffle: основы и параметры
Функция random.shuffle() из модуля random в Python предназначена для перемешивания изменяемых последовательностей на месте. Её основное применение – случайное изменение порядка элементов в списках, что полезно в задачах рандомизации, статистического моделирования, игровых механиках и машинном обучении.
Сигнатура функции:
random.shuffle(x, random=None)
Аргументы:
- x (MutableSequence) – обязательный аргумент, изменяемая последовательность (обычно список). Функция изменяет эту последовательность непосредственно, не создавая новую.
- random (callable, optional) – необязательный аргумент, функция, возвращающая случайные числа в диапазоне [0.0, 1.0). По умолчанию используется функция
random.random()из того же модуля.
Возвращаемое значение:
Функция не возвращает значения (возвращает None), так как работает непосредственно с переданной последовательностью.
Особенности работы:
- Для неизменяемых последовательностей (кортежи, строки) использовать нельзя – необходимо преобразовать в список.
- Для многомерных структур (например, списка списков) перемешиваются только элементы первого уровня.
- При использовании пользовательской функции
randomалгоритм перемешивания остается тем же, но источник случайности изменяется.
Базовые примеры использования
Пример 1: Перемешивание простого списка
import random
numbers = [1, 2, 3, 4, 5]
random.shuffle(numbers)
print(numbers)
[3, 5, 1, 4, 2] # Результат будет разным при каждом запуске
Пример 2: Перемешивание списка строк
import random
words = ['яблоко', 'банан', 'вишня', 'дата']
random.shuffle(words)
print(words)
['банан', 'дата', 'вишня', 'яблоко']
Пример 3: Использование пользовательского генератора случайных чисел
import random
import time
def my_random():
return (time.time_ns() % 100) / 100.0
items = ['A', 'B', 'C', 'D', 'E']
random.shuffle(items, my_random)
print(items)
['C', 'A', 'E', 'D', 'B']
Пример 4: Перемешивание вложенных структур
import random
matrix = [[1, 2], [3, 4], [5, 6]]
random.shuffle(matrix)
print(matrix)
[[5, 6], [1, 2], [3, 4]] # Вложенные списки остаются неизменными
Альтернативные функции в Python
Python предлагает несколько функций для работы со случайностью, которые могут применяться в схожих сценариях.
random.sample(population, k) – возвращает новый список длиной k из уникальных элементов последовательности population. Предпочтительнее, когда требуется выбрать подмножество без повторений или когда исходная последовательность не должна изменяться.
import random
result = random.sample([1, 2, 3, 4, 5], 3)
print(result)
[5, 1, 3]
random.choices(population, weights=None, k=1) – возвращает список длиной k с возвращением элементов. Позволяет задавать веса для элементов. Используется, когда нужны повторяющиеся элементы или взвешенный случайный выбор.
import random
result = random.choices(['a', 'b', 'c'], k=4)
print(result)
['b', 'c', 'a', 'b']
numpy.random.shuffle() – аналог из библиотеки NumPy, работающий с массивами numpy. Обеспечивает более высокую производительность для больших числовых массивов и поддерживает многомерные массивы по указанной оси.
import numpy as np
arr = np.array([1, 2, 3, 4])
np.random.shuffle(arr)
print(arr)
[3 1 4 2]
sorted(iterable, key=lambda x: random.random()) – идиоматический способ создания перемешанной копии без изменения оригинала через сортировку по случайному ключу.
import random
original = [10, 20, 30, 40]
shuffled = sorted(original, key=lambda x: random.random())
print(shuffled)
[40, 10, 30, 20]
Аналоги в других языках программирования
JavaScript: метод array.sort() с функцией сравнения, возвращающей случайное значение.
let arr = [1, 2, 3, 4];
arr.sort(() => Math.random() - 0.5);
console.log(arr);
[3, 1, 4, 2]
Java: Collections.shuffle() из стандартной библиотеки.
import java.util.*;
List list = Arrays.asList(1, 2, 3, 4);
Collections.shuffle(list);
System.out.println(list);
[3, 1, 4, 2]
PHP: функция shuffle() работает аналогично, но переиндексирует массив.
$arr = [1, 2, 3, 4];
shuffle($arr);
print_r($arr);
Array ( [0] => 4 [1] => 1 [2] => 3 [3] => 2 )
C#: метод Random.Shuffle() для массивов и списков.
Random rng = new Random();
List list = new List {1, 2, 3, 4};
list = list.OrderBy(x => rng.Next()).ToList();
Console.WriteLine(string.Join(", ", list));
3, 1, 4, 2
Golang: в стандартной библиотеке отсутствует готовая функция, реализуется через интерфейс sort.Interface.
import (
"math/rand"
"time"
)
rand.Seed(time.Now().UnixNano())
arr := []int{1, 2, 3, 4}
rand.Shuffle(len(arr), func(i, j int) {
arr[i], arr[j] = arr[j], arr[i]
})
fmt.Println(arr)
[4 2 1 3]
Kotlin: метод shuffle() для изменяемых коллекций.
val list = mutableListOf(1, 2, 3, 4)
list.shuffle()
println(list)
[3, 1, 4, 2]
Lua: отсутствует встроенная функция, требуется ручная реализация алгоритма Фишера-Йетса.
math.randomseed(os.time())
local t = {1, 2, 3, 4}
for i = #t, 2, -1 do
local j = math.random(i)
t[i], t[j] = t[j], t[i]
end
print(table.concat(t, ", "))
3, 1, 4, 2
SQL: порядок строк по умолчанию не гарантирован, для явного перемешивания используется ORDER BY RAND() в MySQL или ORDER BY random() в SQLite.
SELECT * FROM table_name ORDER BY RAND() LIMIT 5;Типичные ошибки при использовании
Ошибка 1: Попытка перемешать неизменяемую последовательность
import random
tuple_data = (1, 2, 3, 4)
try:
random.shuffle(tuple_data)
except TypeError as e:
print(f"Ошибка: {e}")
Ошибка: 'tuple' object does not support item assignment
Ошибка 2: Непонимание того, что функция изменяет оригинальный список
import random
original = [1, 2, 3, 4]
shuffled = random.shuffle(original)
print("Оригинал:", original)
print("Результат функции:", shuffled)
Оригинал: [2, 4, 1, 3] Результат функции: None
Ошибка 3: Использование строк вместо списка символов
import random
text = "abcd"
try:
random.shuffle(text)
except TypeError as e:
print(f"Ошибка: {e}")
Ошибка: 'str' object does not support item assignment
Ошибка 4: Передача неправильного типа в параметр random
import random
data = [1, 2, 3, 4]
try:
random.shuffle(data, random=0.5)
except TypeError as e:
print(f"Ошибка: {e}")
Ошибка: 'float' object is not callable
Изменения в последних версиях Python
В версии Python 3.11 были внесены изменения в реализацию алгоритма перемешивания. Теперь используется современная версия алгоритма Фишера-Йетса, которая обеспечивает более равномерное распределение.
В Python 3.9 появилась возможность использовать random.shuffle() с пользовательским генератором псевдослучайных чисел через параметр random, что повысило гибкость функции.
Начиная с Python 3.10, улучшена обработка ошибок для некорректных типов аргументов с более понятными сообщениями об ошибках.
Важное изменение в Python 3.11: для очень больших последовательностей (более 2^31 элементов) теперь корректно обрабатываются индексы за счет использования 64-битных целых чисел в реализации.
Расширенные примеры применения
Пример 1: Перемешивание колоды карт
import random
suits = ['♠', '♥', '♦', '♣']
ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
deck = [rank + suit for suit in suits for rank in ranks]
random.shuffle(deck)
print("Первые 5 карт:", deck[:5])
Первые 5 карт: ['10♦', '4♠', 'J♣', '7♥', '2♠']
Пример 2: Создание тестовых данных с перемешанными метками
import random
import numpy as np
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8]])
y = [0, 1, 0, 1]
indices = list(range(len(X)))
random.shuffle(indices)
X_shuffled = X[indices]
y_shuffled = [y[i] for i in indices]
print("Перемешанные признаки:\n", X_shuffled)
print("Перемешанные метки:", y_shuffled)
Перемешанные признаки: [[5 6] [3 4] [7 8] [1 2]] Перемешанные метки: [0, 1, 1, 0]
Пример 3: Параллельное перемешивание нескольких списков
import random
names = ['Анна', 'Борис', 'Виктор', 'Дарья']
scores = [85, 92, 78, 95]
paired = list(zip(names, scores))
random.shuffle(paired)
names_shuffled, scores_shuffled = zip(*paired)
print("Имена:", names_shuffled)
print("Баллы:", scores_shuffled)
Имена: ('Борис', 'Дарья', 'Анна', 'Виктор')
Баллы: (92, 95, 85, 78)
Пример 4: Частичное перемешивание (алгоритм Саттоло)
import random
def sattolo_shuffle(items):
"""Алгоритм Саттоло для создания случайного цикла"""
i = len(items)
while i > 1:
i = i - 1
j = random.randrange(i)
items[i], items[j] = items[j], items[i]
return items
numbers = [1, 2, 3, 4, 5]
print("Результат Саттоло:", sattolo_shuffle(numbers.copy()))
Результат Саттоло: [3, 5, 1, 4, 2]
Пример 5: Воспроизводимое перемешивание с фиксированным seed
import random
def reproducible_shuffle(data, seed=42):
random.seed(seed)
random.shuffle(data)
return data
list1 = [1, 2, 3, 4, 5]
list2 = [1, 2, 3, 4, 5]
print("Первый запуск:", reproducible_shuffle(list1, 42))
print("Второй запуск:", reproducible_shuffle(list2, 42))
Первый запуск: [2, 5, 1, 3, 4] Второй запуск: [2, 5, 1, 3, 4]
Пример 6: Взвешенное перемешивание через кастомную random-функцию
import random
import bisect
def weighted_shuffle(items, weights):
"""Перемешивание с учётом весов элементов"""
cumulative_weights = []
total = 0
for w in weights:
total += w
cumulative_weights.append(total)
def weighted_random():
return bisect.bisect_left(cumulative_weights, random.random() * total)
return sorted(items, key=lambda x: weighted_random())
colors = ['красный', 'зеленый', 'синий']
weights = [0.7, 0.2, 0.1]
print("Взвешенное перемешивание:", weighted_shuffle(colors, weights))
Взвешенное перемешивание: ['красный', 'зеленый', 'синий']