LoginSignup
4
3

More than 3 years have passed since last update.

python3.9の新機能 辞書のマージ

Posted at

python3.9の新機能 辞書のマージ

概要

2020/10/05にPython3.9がリリースされました。今回の新機能の一つとして、辞書(dict)のマージ演算子があります。このマージ演算子を使うことで、これまでより簡単に辞書を併合できるようになります。

お試し環境構築(要Docker)

以下の手順でPython3.9をDockerコンテナ上で実行できます。

以下の手順はDockerコンテナ上で動させるため、ホストのPythonバージョンを更新せずにPython3.9を検証できます。

1. docker hubのアカウント作成(アカウントを持っていない場合のみ)。

2. ターミナルからdocker login

$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: # ここでdocker hubのユーザ名を入力してEnterキー
Password: # ここでdocker hubのパスワードを入力してEnterキー

以下の表示が出ればログイン成功

Login Succeeded

3. python3.9のDocker imageをdocker hubからpullする

$ docker pull python:3.9
 3.9: Pulling from library/python
e4c3d3e4f7b0: Pull complete 
101c41d0463b: Pull complete 
8275efcd805f: Pull complete 
751620502a7a: Pull complete 
0a5e725150a2: Pull complete 
397dba5694db: Pull complete 
b1d09d0eabcb: Pull complete 
475299e7c7f3: Pull complete 
d2fe14d8e6bc: Pull complete 
Digest: sha256:429b2fd1f6657e4176d81815dc9e66477d74f8cbf986883c024c9b97f7d4d5a6
Status: Downloaded newer image for python:3.9
docker.io/library/python:3.9

4. docker imageからコンテナを起動し、コンテナ内のPythonを対話モードで起動する

$ docker run -it python:3.9 python3
Python 3.9.0 (default, Oct 13 2020, 20:14:06)  # ←Python3.9が起動している
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

マージ演算子

2つの辞書を組み合わせて1つの辞書を作る場合を考えます。

>> dict_1 = {"name": "Alice", "age": 29}
>> dict_2 = {"mail": "alice@example.com", "tel": "000-0000-0000"}

# 上の2つのdictを組み合わせて以下のdictを作る
dict_3 = {'name': 'Alice', 'age': 29, 'mail': 'alice@example.com', 'tel': '000-0000-0000'}

従来のPythonでは、dictのitemsでループしてdict_2の要素を1つずつdict_1に代入していました。

>> dict_3 = dict_1.copy() # dict_3 = dict_1だとdict_1も書き換わるので注意
>>> for key, value in dict_2.items():
...   dict_3[key] = value
...
>>> dict_3
{'name': 'Alice', 'age': 29, 'mail': 'alice@example.com', 'tel': '000-0000-0000'}
>>> dict_1
{'name': 'Alice', 'age': 29} # マージ後もdict_1は変化しない
>>> dict_2
{'mail': 'alice@example.com', 'tel': '000-0000-0000'} # マージ後もdict_2は変化しない

Python3.9では上のような処理がマージ演算子だけで完結します

>>> dict_3 = dict_1 | dict_2 # | がマージ演算子
>>> dict_3
{'name': 'Alice', 'age': 29, 'mail': 'alice@example.com', 'tel': '000-0000-0000'}

マージ演算子を使うことで、dict_1とdict_2を併合する処理が1行で記述できます。

2つのdictに同じキーが存在する場合は、マージ後の値は右辺のものになります(後勝ち)。

>>> dict_1 = {"name": "Alice", "age": "29"}
>>> dict_2 = {"mail": "alice@example.com", "tel": "000-0000-0000", "age": 30} # "age"がdict_1とdict_2の両方に含まれている
>>> dict_1 | dict_2
{'name': 'Alice', 'age': 30, 'mail': 'alice@example.com', 'tel': '000-0000-0000'} # ageがdict_2のものになっている
>>> dict_1 = {"name": "Alice", "age": "29"}
>>> dict_2 = {"mail": "alice@example.com", "tel": "000-0000-0000", "age": None}
>>> dict_1 | dict_2
{'name': 'Alice', 'age': None, 'mail': 'alice@example.com', 'tel': '000-0000-0000'} # 右辺の値がNoneでも併合後の辞書に入るので注意(左辺の値にはならない)

マージ演算子の代入文

+や-などの他の演算子と同様、=をつけることでマージ後のdictを左辺へ代入することができます。

>>> dict_1 = {"name": "Alice", "age": 29}
>>> dict_2 = {"mail": "alice@example.com", "tel": "000-0000-0000"}
>>> id(dict_1), id(dict_2)
(140606638257856, 140606638701760)
>>> dict_1 |= dict_2 # dict_1とdict_2をマージした結果をdict_1に代入
>>> dict_1
{'name': 'Alice', 'age': 29, 'mail': 'alice@example.com', 'tel': '000-0000-0000'} # dict_1は書き換わる
>>> dict_2
{'mail': 'alice@example.com', 'tel': '000-0000-0000'} # dict_2は変化しない
>>> id(dict_1), id(dict_2)
(140606638257856, 140606638701760) # idは演算前後で同一

マージ演算子とOrderedDict

マージ演算子はOrderedDict(順序付き辞書)に対しても使うことができます。

>>> from collections import OrderedDict
>>> o_dict_1 = OrderedDict({'name': 'Alice', 'age': 29})
>>> o_dict_2 = OrderedDict({'mail': 'alice@example.com', 'tel': '000-0000-0000'})
>>> o_dict_1
OrderedDict([('name', 'Alice'), ('age', 29)])
>>> o_dict_1 | o_dict_2
OrderedDict([('name', 'Alice'), ('age', 29), ('mail', 'alice@example.com'), ('tel', '000-0000-0000')])

左辺と右辺に共通するキーがある場合は、並び順は左辺、値は右辺のものになります。

右辺にのみ含まれるキーは右辺の並び順のまま末尾に追加されます。

>>> from collections import OrderedDict
>>> o_dict_1 = OrderedDict({'name': 'Alice', 'age': 29})
>>> o_dict_2 = OrderedDict({'mail': 'bob@example.com', 'age': 30, 'name': 'Bob', 'tel': '000-0000-0000'})
>>> o_dict_1 | o_dict_2
OrderedDict([('name', 'Bob'), ('age', 30), ('mail', 'bob@example.com'), ('tel', '000-0000-0000')])
# age, nameはo_dict_1の順序でo_dict_2の値で並んでいる。
# dict_2のみに含まれるmail, telはo_dict_2の順番で末尾に追加される
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3