モジュールと標準ライブラリ
Python には、すぐに使える膨大なツール群が同梱されています。乱数、数学、日付、ファイルパスなど、その他多数です。これらのツールは モジュール に収められており、import を使ってコードに取り込みます。前章で import json をすでに使いましたね。本章では import を完全に解説し、標準ライブラリの最も便利な部分を紹介します。
モジュールのインポート
最もシンプルな import は、モジュール全体を取り込み、ドット記法でその内容を使えるようにします。特定の名前だけをモジュールからインポートすることもでき、その場合は接頭辞なしで直接使えます。エイリアスを使えば長い名前を短くできます。
import math
math.sqrt(16) # 4.0
math.pi # 3.141592653589793
math.floor(3.9) # 3
math.ceil(3.1) # 4モジュールから特定の名前をインポートして、直接使う:
from math import sqrt, pi
sqrt(16) # 4.0 ("math." 接頭辞は不要)
pi # 3.141592653589793モジュールや名前にエイリアスを付けて短くする:
import math as m
m.sqrt(16) # 4.0
from math import sqrt as square_root
square_root(25) # 5.0エイリアスは人気のサードパーティライブラリ (import numpy as np、import pandas as pd) でよく使われます。標準ライブラリのモジュールでは、フルネームを使うほうがコードが読みやすくなります。
random
random モジュールは乱数を生成し、ランダムな選択を行います。ゲーム、シミュレーション、ランダムサンプリングなど、予測不能性が必要なあらゆる場面で使えます。シード を設定すると結果が再現可能になります。同じシードからは毎回同じ系列が生成されます。
import random
random.random() # 0 以上 1 未満の float
random.randint(1, 10) # 1 から 10 までの整数 (両端含む)
random.uniform(1.0, 10.0) # 1.0 から 10.0 の間の float
colours = ["red", "green", "blue"]
random.choice(colours) # 1 要素を選ぶ
random.choices(colours, k=3) # k 個選ぶ (重複あり)
random.sample(colours, k=2) # k 個選ぶ (重複なし)
numbers = [1, 2, 3, 4, 5]
random.shuffle(numbers) # インプレースでシャッフル、None を返す再現可能な結果が必要な場合 (テストやデータサイエンスで便利)、生成前に シード を設定します:
random.seed(42)
random.randint(1, 100) # シード 42 では常に同じ値同じシードからは、どのマシンでも毎回同じ系列が生成されます。
math
math モジュールは、基本的な算術演算子を超える、より高度な数学演算を追加します。平方根、べき乗、対数、三角関数、そして pi や無限大などの特殊値もここにあります。
import math
math.sqrt(25) # 5.0
math.pow(2, 10) # 1024.0 (2 ** 10 と同じだが常に float を返す)
math.log(100, 10) # 2.0 (底 10 の log)
math.log(math.e) # 1.0 (自然対数)
math.sin(math.pi / 2) # 1.0
math.cos(0) # 1.0
math.ceil(3.2) # 4
math.floor(3.9) # 3
math.trunc(3.9) # 3 (正の値では int() と同じ)
math.inf # 無限大
math.isnan(float("nan")) # True
math.isinf(math.inf) # Truedatetime
datetime モジュールは日付と時刻を扱います。datetime.now() は現在の日付と時刻を返します。strftime() は文字列としてフォーマットします。strptime() は文字列を datetime に変換します。timedelta は加算・減算できる期間を表します。
from datetime import datetime, date, timedelta
now = datetime.now() # 現在の日付と時刻
today = date.today() # 現在の日付のみ
print(now.year, now.month, now.day)
print(now.hour, now.minute, now.second)
# フォーマット
print(now.strftime("%Y-%m-%d")) # "2024-01-15"
print(now.strftime("%d %B %Y, %H:%M")) # "15 January 2024, 09:42"
# 解析
deadline = datetime.strptime("2024-12-31", "%Y-%m-%d")
# 算術演算
tomorrow = today + timedelta(days=1)
next_week = today + timedelta(weeks=1)
diff = deadline - now
print(f"{diff.days} days until deadline")よく使われる strftime コード:
| コード | 意味 | 例 |
|---|---|---|
%Y | 4 桁の年 | 2024 |
%m | 月 (ゼロ埋め) | 01 |
%d | 日 (ゼロ埋め) | 15 |
%H | 時 (24時間) | 09 |
%M | 分 | 42 |
%B | 月の完全な名前 | January |
os と pathlib
pathlib はファイルパスを扱う現代的な方法です。Path オブジェクトを使うと、/ 演算子でパスを構築・検査・ナビゲートできます。os は環境変数や低レベルの OS 操作にアクセスできます。新しいコードでは pathlib を優先しましょう。
from pathlib import Path
p = Path("data/reports")
p.exists() # パスが存在すれば True
p.is_dir() # ディレクトリなら True
p.is_file() # ファイルなら True
p.mkdir(parents=True, exist_ok=True) # ディレクトリを作成
for f in p.glob("*.csv"): # ディレクトリ内のすべての CSV ファイル
print(f.name) # ファイル名のみ
report = p / "report_jan.csv" # / 演算子でパスを連結
report.stem # "report_jan" (拡張子なしの名前)
report.suffix # ".csv"
report.parent # Path("data/reports")
content = report.read_text() # ファイル内容を直接読み込む
report.write_text("new content\n") # 直接書き込むos モジュール:
import os
os.getcwd() # 現在の作業ディレクトリ
os.listdir(".") # ディレクトリの中身を一覧
os.path.exists("data.txt") # パスが存在すれば True
os.path.join("data", "file.txt") # "data/file.txt" (クロスプラットフォーム)
os.environ.get("HOME") # 環境変数を読み取る新しいコードでは pathlib を優先しましょう。環境変数が必要な場合や、文字列を期待する古い API を扱う場合は os を使います。
timeit
timeit はコードの実行時間を計測します。2 つの手法を比較してより速いほうを選びたいときに便利です。安定した計測値を得るには、コードを何回も実行します。
import timeit
# 単一の文を計測
timeit.timeit("sum(range(1000))", number=10000)
# より複雑なブロックを計測
setup = "data = list(range(1000))"
code = "[x * 2 for x in data]"
time = timeit.timeit(code, setup=setup, number=10000)
print(f"{time:.4f} seconds for 10,000 runs")number は繰り返す回数です。繰り返し回数を増やすほど計測値が安定します。
string
string モジュールは、文字、数字、句読点用のあらかじめ用意された文字列定数を提供します。文字をチェックしたり、特定のアルファベットから乱数文字列を生成したりするときに便利です。
import string
string.ascii_lowercase # "abcdefghijklmnopqrstuvwxyz"
string.ascii_uppercase # "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
string.ascii_letters # 両方を結合したもの
string.digits # "0123456789"
string.punctuation # すべての句読点文字をチェックしたり、ランダムな文字列を生成したりするときに便利です:
import string, random
chars = string.ascii_letters + string.digits
password = "".join(random.choices(chars, k=12))自分自身のモジュールを作成する
すべての Python ファイルはモジュールです。別のファイルから使うには、ファイル名で (.py を付けずに) インポートします。モジュール全体をインポートしてドット記法で内容を使うこともできますし、特定の名前を直接インポートすることもできます。
# utils.py
def clamp(value, lo, hi):
return max(lo, min(value, hi))
PI = 3.14159# main.py
import utils
utils.clamp(150, 0, 100) # 100
utils.PI # 3.14159
from utils import clamp
clamp(50, 0, 100) # 50Python はインポートするファイルと同じディレクトリ (および他のいくつかの場所) を見てモジュールを探します。大規模なプロジェクトでは、モジュールは パッケージ (__init__.py ファイルを持つディレクトリ) として整理されます。
__name__ == "__main__"
Python がファイルを直接実行すると、__name__ は "__main__" に設定されます。同じファイルがモジュールとして import されると、__name__ はモジュール名になります。このパターンを使えば、ファイルを直接実行したときに動くが、別のモジュールから import されたときには動かないコードを書けます。
# utils.py
def clamp(value, lo, hi):
return max(lo, min(value, hi))
if __name__ == "__main__":
# これは python utils.py を実行したときだけ動く
# import utils したときには動かない
print(clamp(150, 0, 100)) # 100これは、スタンドアロンスクリプトとしても役立つあらゆるモジュールに対する標準的なパターンです。
標準ライブラリの注目モジュール
知っておく価値があるさらにいくつかのモジュールです。それぞれが、自分で実装しようとするとかなりの労力が必要となる一般的な問題を解決してくれます。
collections: 特殊なコンテナ型:
from collections import Counter, defaultdict, deque
Counter(["a", "b", "a", "c", "a"]) # Counter({'a': 3, 'b': 1, 'c': 1})
defaultdict(list) # 欠落キーを自動生成する辞書
deque([1, 2, 3], maxlen=5) # 両端からの append/pop が高速itertools: イテラブルを扱うツール:
import itertools
list(itertools.chain([1, 2], [3, 4])) # [1, 2, 3, 4]
list(itertools.islice(range(100), 5)) # [0, 1, 2, 3, 4]
list(itertools.combinations([1, 2, 3], 2)) # [(1, 2), (1, 3), (2, 3)]
list(itertools.product([0, 1], repeat=2)) # [(0,0), (0,1), (1,0), (1,1)]sys: Python インタプリタへのアクセス:
import sys
sys.argv # コマンドライン引数のリスト
sys.exit(1) # ステータスコードを指定して終了
sys.version # Python バージョンの文字列サードパーティパッケージ: 標準ライブラリ以外に、pip でコミュニティパッケージをインストールできます:
pip install requests # HTTP ライブラリ
pip install pandas # データ操作
pip install numpy # 数値計算サードパーティパッケージは本ガイドの範囲外ですが、パターンは常に同じです: pip install してから import するだけです。
実践例
random、string、datetime を組み合わせて、タイムスタンプ付きのユニークなゲーム ID を生成する例:
import random
import string
from datetime import datetime
def generate_game_id(length: int = 8) -> str:
chars = string.ascii_uppercase + string.digits
return "".join(random.choices(chars, k=length))
def timestamp() -> str:
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
game_id = generate_game_id()
print(f"[{timestamp()}] Starting game {game_id}")
scores = [random.randint(50, 100) for _ in range(5)]
print(f"Round scores: {scores}")
print(f"Best: {max(scores)}")
