乱数はゲームの出目やデータのサンプリングなど、初心者から上級者まで幅広い場面で使われます。
本記事ではPython標準ライブラリのrandom
モジュールを取り上げ、randint
、choice
、shuffle
の基本を丁寧に解説します。
再現性(シード)や注意点も押さえながら、安全に使える知識を身につけましょう。
Pythonの乱数(random)の基本
Pythonで乱数を扱うときはrandom
モジュールを使います。
randomは「疑似乱数」であり、内部状態(シード)に基づいて見かけ上ランダムな値を生成します。
再現可能なテストを行いたい場合はrandom.seed(数値)
でシードを固定することができます。
逆に、セキュリティ用途(パスワードやトークン生成)ではrandomを使わず、secrets
モジュールを使います。
randomモジュールの読み込みと代表的な関数
最初にモジュールを読み込みます。
ここでは全体像だけを掴み、具体例は後続の章で扱います。
# randomモジュールをインポート
import random
# 0.0以上1.0未満の浮動小数点数
x = random.random()
# 区間[a, b]の整数(両端を含む) 例: 1〜6のどれか
d = random.randint(1, 6)
# シーケンスから1要素をランダムに選ぶ
item = random.choice(["apple", "banana", "cherry"])
# リストの要素順をシャッフル(破壊的)
cards = [1, 2, 3, 4, 5]
random.shuffle(cards)
print(x, d, item, cards)
出力例(実行のたびに異なります):
0.234567890123 3 banana [4, 2, 5, 1, 3]
シードと再現性のポイント
テストや学習では結果を固定したいことがよくあります。
random.seed(123)
のように設定すると、その後の乱数列が同じになります。
これにより、説明用の実行結果やユニットテストの安定性が保てます。
なお、randomのアルゴリズムは実装依存であり将来的に変更される可能性がありますが、現行のCPythonではMersenne Twisterが用いられています。
本記事で扱う関数の位置づけ
関数名 | 主な用途 | 代表的な引数 | 返り値 | 破壊的変更 |
---|---|---|---|---|
randint(a, b) | 整数の乱数 | 下限a, 上限b(両端含む) | int | いいえ |
choice(seq) | シーケンスから1要素選択 | リスト・タプル・文字列など | 要素1つ | いいえ |
shuffle(lst) | リストをシャッフル | 変更可能シーケンス(リスト) | None | はい |
このあと、それぞれの使い方を具体例で解説します。
randintの使い方(整数の乱数)
指定範囲の整数を1つ生成
randint(a, b)
は区間[a, b]の両端を含む形で、整数を1つ返します。
最小値と最大値を含むことがポイントです。
import random
# 1〜10の整数を1つ取得
n = random.randint(1, 10)
print(f"1〜10の乱数: {n}")
# マイナスの範囲でもOK (-5〜5)
m = random.randint(-5, 5)
print(f"-5〜5の乱数: {m}")
1〜10の乱数: 7
-5〜5の乱数: -2
例外と境界の注意
a > b を渡すと ValueErrorになります。
範囲はa <= 値 <= b
の関係を満たします。
範囲は両端を含むことに注意
Pythonのrange
は上端を含みませんが、randint
は上端を含みます。
これを混同しやすいので注意しましょう。
たとえば、サイコロ(1〜6)はrandom.randint(1, 6)
と書きます。
両端が含まれることのイメージを、可能な値の集合で確認します。
# randint(1, 6) の取りうる値は 1,2,3,4,5,6 の6通り
possible = set(range(1, 6 + 1))
print(possible)
{1, 2, 3, 4, 5, 6}
サイコロを振る例
実際にサイコロの出目を複数回表示してみます。
import random
def roll_dice(times=5):
"""サイコロ(1〜6)を指定回数振って表示する"""
for i in range(1, times + 1):
face = random.randint(1, 6) # 両端(1と6)を含む
print(f"{i}回目の出目: {face}")
# 5回振る
roll_dice(5)
1回目の出目: 4
2回目の出目: 1
3回目の出目: 6
4回目の出目: 2
5回目の出目: 5
choiceの使い方(リストから1つ選ぶ)
シーケンスからランダムに1件選択
random.choice(seq)
はシーケンス(リスト・タプル・文字列)から1要素をランダムに返す関数です。
等確率で選ばれます。
import random
colors = ["red", "green", "blue", "yellow"]
picked = random.choice(colors)
print(f"選ばれた色: {picked}")
# 文字列から1文字を選ぶことも可能
ch = random.choice("PYTHON")
print(f"選ばれた文字: {ch}")
選ばれた色: green
選ばれた文字: T
空のリストはエラーになる
空のシーケンスは選べないため、IndexError
が発生します。
事前に長さを確認するか、例外を処理しましょう。
import random
items = []
try:
random.choice(items)
except IndexError as e:
print(f"空からは選べません: {e}")
空からは選べません: Cannot choose from an empty sequence
少し厳密に言うと、choice
は「インデックスアクセスが可能なシーケンス」を想定しています。
集合(set
)のような順序なしコレクションは直接使えないのでlist()
などで変換します。
メニューから1つ選ぶ例
ランチメニューから今日の一品を決める例です。
簡単ですが実用的なパターンです。
import random
menu = ["ラーメン", "カレー", "定食", "サンドイッチ", "パスタ"]
today = random.choice(menu)
print(f"今日のランチは: {today}")
今日のランチは: 定食
shuffleの使い方(リストを並び替え)
リストをその場でシャッフル(破壊的変更)
random.shuffle(lst)
はリストの要素順をその場で並び替えます(破壊的変更)。
元の順序は失われるため、残しておきたい場合は先にコピーを作ってください。
import random
nums = [1, 2, 3, 4, 5]
print("シャッフル前:", nums)
random.shuffle(nums) # 破壊的に並び替え
print("シャッフル後:", nums)
# 元の順序を残したい場合
nums2 = [1, 2, 3, 4, 5]
shuffled_copy = nums2[:] # スライスで浅いコピー
random.shuffle(shuffled_copy)
print("元:", nums2)
print("コピーをシャッフル:", shuffled_copy)
シャッフル前: [1, 2, 3, 4, 5]
シャッフル後: [3, 1, 5, 2, 4]
元: [1, 2, 3, 4, 5]
コピーをシャッフル: [2, 5, 1, 3, 4]
戻り値はNoneに注意
shuffleの戻り値はNone
です。
関数が結果を返すのではなく、引数のリスト自体が書き換えられる点に注意しましょう。
import random
values = [10, 20, 30, 40]
result = random.shuffle(values)
print("戻り値:", result) # None
print("values:", values) # 並び替え済み
戻り値: None
values: [30, 10, 40, 20]
もし非破壊でシャッフルしたい場合は、random.sample(values, k=len(values))
を使うと新しいリストが得られます。
import random
values = [10, 20, 30, 40]
shuffled_new = random.sample(values, k=len(values)) # 新しいリスト
print("元:", values)
print("新しいシャッフル:", shuffled_new)
元: [10, 20, 30, 40]
新しいシャッフル: [20, 40, 10, 30]
トランプをシャッフルする例
52枚のトランプデッキを作ってシャッフルし、上から数枚を表示します。
実用的なサンプルとして、デッキ生成→シャッフル→配るの一連の流れを示します。
import random
# スートとランクを定義
suits = ["♠", "♥", "♦", "♣"]
ranks = ["A"] + [str(n) for n in range(2, 10)] + ["10", "J", "Q", "K"]
# 52枚のデッキを生成
deck = [f"{s}{r}" for s in suits for r in ranks]
print("シャッフル前の先頭5枚:", deck[:5])
# 破壊的にシャッフル
random.shuffle(deck)
print("シャッフル後の先頭5枚:", deck[:5])
# 上から5枚配る(取り出し)
hand = deck[:5]
print("配られた手札:", hand)
print("残り枚数:", len(deck) - len(hand))
シャッフル前の先頭5枚: ['♠A', '♠2', '♠3', '♠4', '♠5']
シャッフル後の先頭5枚: ['♦Q', '♠8', '♥10', '♣2', '♦6']
配られた手札: ['♦Q', '♠8', '♥10', '♣2', '♦6']
残り枚数: 47
補足として、タプルや文字列はイミュータブルなのでshuffle
できません。
その場合はlist()
でリスト化してから使います。
まとめ
本記事ではPython標準のrandom
モジュールから、randint
、choice
、shuffle
の基本を解説しました。
randintは両端を含む整数、choiceはシーケンスから1件選択、shuffleはリストを破壊的に並び替える点が核となる知識です。
再現性が必要な場面ではrandom.seed()
を活用し、セキュリティ用途ではsecrets
を選ぶという使い分けも忘れないでください。
これらの基礎が身につけば、ゲームのロジックやデータサンプリングなど、さまざまなプログラムで乱数を安全かつ効果的に扱えるようになります。