[解決!Python]ランダムな文字列を生成するには解決!Python

randomモジュールのrandint関数やchoice関数、choices関数とstringモジュールで定義されている定数を組み合わせてランダムな文字列を生成する方法を紹介する。

» 2024年10月01日 05時00分 公開
[かわさきしんじDeep Insider編集部]
「解決!Python」のインデックス

連載目次

import random

# random.randint関数とchr関数を使う例
start = ord('a')
end = ord('z')
n = 10

tmp = [chr(random.randint(start, end)) for _ in range(n)]
result = ''.join(tmp)
print(result)  # 出力例:rhnravmvxd

# random.choice関数とchr関数を使う例
tmp = [chr(random.choice(range(start, end+1))) for _ in range(n)]
result = ''.join(tmp)
print(result)  # 出力例:xprounzvjn

# random.choices関数はシーケンスを取り扱うので文字列を与えてもよい
lowercases = 'abcdefghijklmnopqrstuvwxyz'
tmp = [random.choice(lowercases) for _ in range(n)]
result = ''.join(tmp)
print(result)  # 出力例:bchjeiuevi

# ASCII文字のコードポイントは連続していない
start = ord('A')
end = ord('z')
tmp = [chr(random.randint(start, end)) for _ in range(n)]
result = ''.join(tmp)
print(result)  # 出力例:SEo[jypUNa

# random.choices関数を使う例
lowercases = 'abcdefghijklmnopqrstuvwxyz'
uppercases = lowercases.upper()
letters = lowercases + uppercases
tmp = random.choices(letters, k=n)
result = ''.join(tmp)
print(result)  # 出力例:sKbUUDAKXj

# stringモジュールを使う例
from string import ascii_lowercase, ascii_uppercase, ascii_letters, digits

print(ascii_lowercase)  # abcdefghijklmnopqrstuvwxyz
print(ascii_uppercase)  # ABCDEFGHIJKLMNOPQRSTUVWXYZ
print(ascii_letters)  # abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
print(digits)  # 0123456789

def get_random_string(n, lower=True, upper=True, numbers=False):
    chars = ''
    if lower:
        chars += ascii_lowercase
    if upper:
        chars += ascii_uppercase
    if numbers:
        chars += digits

    return ''.join(random.choices(chars, k=n))

result = get_random_string(10, numbers=True)
print(result)  # 出力例:8yoUtn9vYM


ランダムな文字列を作成する幾つかの方法

 辞書のキーにするなどの目的で、(意味はなくてもよいので)ランダムな文字列を作成したくなる場合がある。簡単に考えつくのは以下のような方法だ。

import random

start = ord('a')
end = ord('z')
n = 10

tmp = [chr(random.randint(start, end)) for _ in range(n)]
result = ''.join(tmp)
print(result)  # 出力例:rhnravmvxd


 これはrandomモジュールのrandint関数*1に、生成する文字列の範囲として'a'から'z'を指定して、その範囲に含まれる文字のいずれかを変数nに指定した数(ここでは10)だけchr関数で生成して、最後に1つの文字列にまとめている(上のリスト内包表記は個々の文字を要素とするリストが生成される)。

*1 この記事で紹介するrandint関数などは実際にはrandom.Randomクラスのメソッドだ。だが、randomモジュールのドキュメントでは「整数用の関数」などと表現されているとともに「random.randint(start, end)」のように関数的に使っているので、ここでも関数という呼び方をする。


 これと同じことはrandomモジュールのchoice関数を使っても記述できる。

tmp = [chr(random.choice(range(start, end+1))) for _ in range(n)]
result = ''.join(tmp)
print(result)  # 出力例:xprounzvjn


 ここで使用しているrandom.choice関数は与えられたシーケンスからランダムに要素を1つ取り出す。上のコードではrange関数で生成する文字の範囲を指定することで、その範囲からランダムにコードポイントを取り出し、chr関数で対応する文字を得ている(それを文字数nだけ繰り返す)。range関数には終端としてord('z')+1を指定する必要がある点には注意が必要だ。

 上のコードではrange関数を使って文字範囲を指定しているが、random.choice関数はシーケンスを受け取るので、単純に文字列を指定するだけでもよい。以下がその例だ。

lowercases = 'abcdefghijklmnopqrstuvwxyz'
tmp = [random.choice(lowercases) for _ in range(n)]
result = ''.join(tmp)
print(result)  # 出力例:bchjeiuevi


 この例では小文字アルファベットを列挙した文字列lowercasesを作成し、それをrandom.choice関数に渡している。ord関数でコードポイントを得るよりも、こちらの方が直感的かもしれない。

 ASCIIの範囲で小文字と大文字(と数字)のコードポイントが連続していない点も考慮する必要があるかもしれない。例えば、アルファベットの大文字小文字だけからなるランダムな文字列を得ようとして、以下のようなコードを書くと記号類が混在する文字列が得られることもある(以下を何度か試すと、そうした結果が得られるはずだ)。

start = ord('A')
end = ord('z')
tmp = [chr(random.randint(start, end)) for _ in range(n)]
result = ''.join(tmp)
print(result)  # 出力例:SEo[jypUNa


 こうしたことからも生成したい文字の範囲を文字列の形で直接指定するのが適切だろう。

 また、これまでのコードでは必要な数の文字を得るためにリスト内包表記を使っていたが、random.choices関数でkパラメーターに取り出す要素の数を指定すると、リスト内包表記を使わなくても同じことができる。random.choices関数は渡したシーケンスからランダムに要素を取り出した要素数kのリストを返す関数だ(要素の重複あり)。

lowercases = 'abcdefghijklmnopqrstuvwxyz'
uppercases = lowercases.upper()
letters = lowercases + uppercases
tmp = random.choices(letters, k=n)
result = ''.join(tmp)
print(result)  # 出力例:sKbUUDAKXj


 この例ではアルファベット小文字からなる文字列lowercasesと大文字からなる文字列uppercasesと、それらをまとめた文字列lettersを作成し、random.choices関数には文字列lettersと要素数としてn(=10)を渡している。リスト内包表記を使わないのでスッキリとしたコードになっているのが分かる。

 特定の文字範囲をrandom.choice関数やrandom.choices関数に渡すのであれば、上のコードのようにそれらをまとめた文字列をいちいち定義する必要があるが、stringモジュールにはアルファベット小文字や大文字、大文字と小文字、数字などを定義した定数が定義されている(ドキュメントでは定数とあるが、実際には変更可能なことには注意)。

from string import ascii_lowercase, ascii_uppercase, ascii_letters, digits

print(ascii_lowercase)  # abcdefghijklmnopqrstuvwxyz
print(ascii_uppercase)  # ABCDEFGHIJKLMNOPQRSTUVWXYZ
print(ascii_letters)  # abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
print(digits)  # 0123456789


 これらの値とrandom.choices関数を組み合わせて、ランダムな文字列を得る関数を定義すると次のようになるだろう。

def get_random_string(n, lower=True, upper=True, numbers=False):
    chars = ''
    if lower:
        chars += ascii_lowercase
    if upper:
        chars += ascii_uppercase
    if numbers:
        chars += digits

    return ''.join(random.choices(chars, k=n))

result = get_random_string(10, numbers=True)
print(result)  # 出力例:8yoUtn9vYM


 ここではlowerパラメーター、upperパラメーター、numbersパラメーターにTrue/Falseを指定することで、どの種類の文字列からランダムな文字列を生成するかを指定できるようにしている。

「解決!Python」のインデックス

解決!Python

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

AI for エンジニアリング
「サプライチェーン攻撃」対策
1P情シスのための脆弱性管理/対策の現実解
OSSのサプライチェーン管理、取るべきアクションとは
Microsoft & Windows最前線2024
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。