Python dict型でgetメソッドを使おう。(KeyError対策)

2018.05.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS LambdaでPythonをよく使用しているのですが、KeyErrorを発生させてしまうことがありましたので対応方法について調べてみました。

KeyErrorは存在しないキーを使用した際に発生します。

>>> email = {
...     "user1": "user1@example.com",
...     "user2": "user2@example.com",
...     "user3": "user3@example.com"
... }
>>>
>>> def get_email_address(user_id):
...     return "%s のメールアドレスは %s です。" % (user_id, email[user_id])
...
>>> get_email_address("user1")
'user1 のメールアドレスは user1@example.com です。'
>>> get_email_address("user4")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in get_email_address
KeyError: 'user4'

対応方法

try-except文を使用する

exceptionが発生したらどのように処理をするかtry-exceptステートメントをよく使うと思います。

>>> def get_email_address(user_id):
...     try:
...             return "%s のメールアドレスは %s です。" % (user_id, email[user_id])
...     except KeyError:
...             return "%s のメールアドレスはありません。" % user_id
...
>>> get_email_address("user1")
'user1 のメールアドレスは user1@example.com です。'
>>> get_email_address("user4")
'user4 のメールアドレスはありません。'

in演算子とif文を使用する

in演算子は値があるか調べてくれます。値が存在したらTrue,存在していなければFalseを返します。in演算子とif文を使用した場合以下のようになります。

>>> def get_email_address(user_id):
...     if user_id in email:
...             return "%s のメールアドレスは %s です。" % (user_id, email[user_id])
...     else:
...             return "%s のメールアドレスはありません。" % user_id
...
>>> get_email_address("user1")
'user1 のメールアドレスは user1@example.com です。'
>>> get_email_address("user4")
'user4 のメールアドレスはありません。'

getメソッドを使用する dict.get(key[, default])

getメソッドは指定されたキーがdictにあれば値を返し、なければデフォルトでNone、指定されていれば第2引数の値を返します。デフォルトではNoneが返されるので、比較するときにも使用できそうです。

デフォルト

>>> def get_email_address(user_id):
...     return "%s のメールアドレスは %s です。" % (user_id, email.get(user_id))
...
>>> get_email_address("user1")
'user1 のメールアドレスは user1@example.com です。'
>>> get_email_address("user4")
'user4 のメールアドレスは None です。'

引数を入れた場合

>>> def get_email_address(user_id):
...     return "%s のメールアドレスは %s です。" % (user_id, email.get(user_id,"ない"))
...
>>> get_email_address("user1")
'user1 のメールアドレスは user1@example.com です。'
>>> get_email_address("user4")
'user4 のメールアドレスは ない です。'

先ほどの「in演算子とif文を使用する」方法より、get()を使用することがベストプラクティスとされてます。 それは「in演算子とif文を使用する」ではdictを2回クエリするからです。 get()であれば、1回のクエリで効率的なことがわかります。

まとめ

KeyError の対応方法についてご紹介しました。同じエラーが発生したときに参考になれば幸いです。

参考URL