概要
Pythonの辞書内包表記を使って、DBへの接続回数を減らす実装を行いました。
以下にサンプルコードを紹介します。
辞書内包表記を使う
例えば、以下のようなコードがあります(DjangoのORMを使用)。
for item in list_fruit_cd:
fruit_data = FruitCd.objects.filter(fruit_cd=item).first()
## 後続処理...
上記だとlist_fruit_cd
の要素数が大量の場合に毎回DBアクセスすることとなり、パフォーマンスに影響が出る可能性もあります。そんな場合に、for
文の外で一度だけDBアクセスさせ、その結果を辞書に格納し、その後のループで辞書から必要なオブジェクトを取得するようにするとパフォーマンスが向上すると思われます。
つまり、以下のようにします。
fruit_dict = {obj.fruit_cd: obj for obj in FruitCd.objects.filter(fruit_cd__in=list_fruit_cd)}
for item in list_fruit_cd:
fruit_obj = fruit_dict.get(item)
## 後続処理...
これにより、for
ループの中で毎回DBにアクセスすることがなくなりました。
クラスを利用したサンプルコード
具体的にサンプルコードを作ってみていきます。
上記はDjangoのORM使用時でしたが、以下のようにPythonのクラスで再現することもできます。
class FruitCd:
def __init__(self, fruit_cd, name):
self.fruit_cd = fruit_cd
self.name = name
list_fruit_cd = [1, 2, 3, 4]
objects = [
FruitCd(1, 'Banana'),
FruitCd(2, 'Lemon'),
FruitCd(3, 'Orange'),
FruitCd(4, 'Apple'),
]
# fruit_cdがlist_fruit_cdに含まれるオブジェクトだけを辞書に変換
fruit_dict = {obj.fruit_cd: obj for obj in objects if obj.fruit_cd in list_fruit_cd}
# 結果を表示
for fruit_cd, obj in fruit_dict.items():
print(f'{fruit_cd}: {obj.name}')
# 出力結果
# 1: Banana
# 2: Lemon
# 3: Orange
# 4: Apple
補足(サンプルコード解説)
fruit_dict = {obj.fruit_cd: obj for obj in objects if obj.fruit_cd in list_fruit_cd}
上記の辞書内包表記の部分ですが、objects
リストからオブジェクトを取り出し、そのオブジェクトのfruit_cd
属性がlist_fruit_cd
に含まれている場合に、新しい辞書fruit_dict
を作成する、というコードです。
fruit_dict
をprint
してみると以下のように返ってくることがわかります。
{1: <__main__.FruitCd object at 0x101127fd0>, 2: <__main__.FruitCd object at 0x101127ee0>, 3: <__main__.FruitCd object at 0x101127e80>, 4: <__main__.FruitCd object at 0x101127e20>}
fruit_cd
をキーとし、そのキーに対応するFruitCd
オブジェクトを値とする辞書が生成されたことを確認できました。
そのあと、for fruit_cd, obj in fruit_dict.items():
のところで、fruit_dict
を反復処理。
fruit_dict.items()
は辞書の各エントリーをキーと値のペア(タプル)として返します。for
ループを使用して、これらのペアを一つずつ取り出し、キーに対応する値を出力するようにしています。