bidictの概要
Pythonの標準的な辞書(dict)は、キーから値へのマッピングを効率的に行いますが、値からキーを逆引きする場合は、ループ処理などを用いる必要があります。bidictライブラリは、この制約を解消し、キーと値の両方向から高速な検索を可能にする双方向マッピング機能を提供します。
bidictの最大の特徴は、キーと値が1対1(一対一)の関係を維持することです。これにより、一貫性のある双方向の参照が可能になります。
ライブラリのインストール
標準のパッケージ管理ツールであるpipを使用してインストールできます。
pip install bidict
基本的な操作方法
1. 双方向マップの作成
bidictオブジェクトは、通常の辞書やタプルのリストから初期化できます。
from bidict import bidict
# HTTPステータスコードの例
http_status = bidict({
"SUCCESS": 200,
"NOT_FOUND": 404,
"SERVER_ERROR": 500
})
# キーから値を検索
print(http_status["SUCCESS"]) # 出力: 200
2. 逆引き(Inverse Lookup)
.inverse属性を使用することで、値からキーを即座に取得できます。
# 値からキーを検索
print(http_status.inverse[404]) # 出力: 'NOT_FOUND'
3. マップの更新と要素の追加
標準の辞書と同様の構文で操作可能ですが、値の重複(一対一の崩壊)が発生しないよう制御されます。
# 新しい要素の追加
http_status["FORBIDDEN"] = 403
# 要素の削除
del http_status["SERVER_ERROR"]
高度な機能と実務的なユースケース
制約の管理と整合性
bidictは一対一の対応を強制するため、既存の値を別のキーに割り当てようとするとValueDuplicationErrorなどの例外が発生します。これによりデータの整合性を保つことができます。
from bidict import ValueDuplicationError
user_mapping = bidict({"user_1": "alice@example.com", "user_2": "bob@example.com"})
try:
# 既存のメールアドレス(値)を新しいユーザー(キー)に割り当てようとする
user_mapping["user_3"] = "alice@example.com"
except ValueDuplicationError as e:
print(f"エラー: 重複した値が検出されました。 {e}")
データの相互変換における活用
例えば、システム間でのID変換や、通貨コードとシンボルの変換などに非常に有効です。以下は社員IDと内部メールアドレスを紐付ける例です。
from bidict import bidict
# 社員情報の紐付け
employee_records = bidict({
1001: "dev_user_a",
1002: "manager_user_b",
1003: "designer_user_c"
})
def get_email_by_id(emp_id):
username = employee_records.get(emp_id)
return f"{username}@company.jp" if username else None
def get_id_by_username(username):
# 逆引きを使用してIDを特定
return employee_records.inverse.get(username)
# 利用例
print(get_email_by_id(1001)) # dev_user_a@company.jp
print(get_id_by_username("manager_user_b")) # 1002
単位変換システムの効率化
計算処理において、基準となる単位と他の単位の関係を双方向で保持することで、変換ロジックを簡潔に記述できます。
from bidict import bidict
# メートルを基準とした長さの倍率
unit_ratios = bidict({
"meter": 1.0,
"kilometer": 1000.0,
"millimeter": 0.001
})
def convert_units(amount, from_unit, to_unit):
# 基準単位(メートル)に変換してから目標単位へ
meters = amount * unit_ratios[from_unit]
return meters / unit_ratios[to_unit]
# 5000ミリメートルをキロメートルに変換
result = convert_units(5000, "millimeter", "kilometer")
print(f"Result: {result} km") # Result: 0.005 km
まとめ
bidictを使用することで、Pythonプログラム内でのデータ検索の柔軟性が大幅に向上します。手動で逆引き用の辞書を管理する手間や、データの同期ミスを防ぐことができるため、複雑なデータ変換が必要なシーンで非常に強力なツールとなります。