日々ブログ

日々のくらしの中で思ったこと

【プログラミング】pythonの乱数作成モジュールの違いまとめ

予約投稿時間ミスった! プログラミングにおいて何かと「乱数」を作成することがありませんか。 モンテカルロシミュレーションのための乱数だったり、パスワードを乱数文字列に変換したり、ゲームを作ったりと乱数はたくさんの場面で使われています。 pythonには乱数モジュールが標準のrandomとsecrets、numpy モジュールの一部であるnumpy.randomがあって、結局どれを使えばいいのか迷っていました。 今回はそれぞれの使い方についてまとめました。 f:id:xinformation:20220215002923p:plain

randomモジュール

python標準についているrandomモジュールです。これだけでも、乱数を作成したいという場合には、十分使用できます。

import random
print(random.random())
-> 0.07949764863927011

pythonの標準ライブラリなので、外部モジュールのインストールが不要です。 昔から使用されているライブラリの一つなので、長寿のプロジェクトで、こちらが使われている場合は、このライブラリを使用しましょう。 乱数モジュールを複数組み込むと、後からプロジェクトに加わった人は「何で乱数モジュールがいっぱいあるの?」と困惑しますから。自分もそうでした。

Point

  • 標準ライブラリなので、外部モジュールのインストールが不要
  • 古くから実装されている乱数モジュールなので、汎用性が高い

numpy.randomモジュール

こちらは数値計算ライブラリのnumpyの一つの機能として乱数機能が組み込まれています。 こちらは、特定の確率分布に従った乱数を生成できます。 たとえば、ポアソン分布に関しても一行で生成可能です。

import numpy as np
print(np.random.poisson(lam=1,size=100))
->[1 1 1 1 1 0 3 0 1 1 1 1 0 1 0 2 0 0 1 1 1 0 1 3 2 1 1 0 1 2 0 3 1 0 2 1 0
 0 0 0 1 1 1 3 1 1 2 4 2 0 1 1 3 1 0 2 2 1 0 1 1 1 1 1 0 1 1 1 3 1 0 1 1 1
 1 3 2 0 0 1 1 3 1 0 1 1 0 1 1 3 0 0 1 1 0 0 2 1 3 0]

一応、その他の分布についても紹介

import numpy as np
np.random.randn()# 正規分布
np.random.normal(loc=a,scale=y,size=c) #平均a, 標準偏差yの 正規分布に従って、c個を生成
np.random.binominal()# 二項分布
np.random.chisquare()# カイ二乗分布

numpy.random最強やんけ!と思いきやそういうわけでもなく、 こちらは標準のrandomモジュールと違って、スレッドセーフではありません。 スレッドセーフというのは、複数のスレッドが同時に処理を始め、このライブラリを使用すると、計算結果が同一になったりと期待する動作が得られなくなります。 複数のスレッドた立ち上がる、webアプリにはあまり向かないでしょうね。科学計算に用いるのが良いと思います。

Point

  • 科学技術計算に適した確率分布に基づいた乱数が生成できる
  • スレッドセーフではないので、シングルスレッド処理に利用すること

secretsモジュール

secretsモジュールですが、こちらは暗号強度が高い乱数文字列を生成することができます。 そのため、パスワードやハッシュ値などセキュリティに関わる機能においてよく使われるモジュールです。最近結構見られるようになった、アカウント登録時の仮パスワードなんかを使うときはこのモジュールを利用しましょう。 たまに古くからのアプリケーションでパスワードの生成に標準のrandomモジュールが使われていますが、公式は非推奨としているので、使われているのを見つけた場合は変更することを検討するのが無難です。 こちらは、乱数文字列を生成することに特化しており、数字を生成した場合は他のモジュールの利用をおすすめします。 ただし、python3.6で標準化されたモジュールなので、それ以前のバージョンでは扱うことができないので注意が必要です。

docs.python.org

Point

  • Secretsモジュールは、パスワードなどセキュリティに関連する乱数としてオススメ
  • python3.6未満では扱えない

まとめ

まとめると下の表のようになるでしょうか。 基本的には標準のrandomモジュールを使用しておけば問題ないと思います。 説明は割愛しましたが、乱数を作成する以外にリストをシャッフルするとかも機能としてはあるのですが、今回の範囲からは外しました。

用途 特徴
random 汎用性 最もシンプルな乱数。スレッドセーフなので安心
numpy.random 科学技術計算 特殊な確率分布に基づいた乱数を生成できるので科学技術計算に適している。スレッドセーフではない。
secrets 暗号生成 セキュリティトークンなど暗号強度の高い乱数を生成。ただし、暗号用なので少数などは扱えない。