【Pythonのデータ構造】辞書(dict)を操作する<定義~要素へのアクセス(追加・更新・削除)>

スポンサーリンク
Pythonの基礎文法(辞書の使い方) Python

重要度:★★★★

Pythonは通常の「データ処理」の他、「AI」や「機械学習」で用いられるライブラリが豊富に提供されている、現在もっとも人気のあるプログラミング言語です。

そのため、他の言語にはない「配列」や「行列・ベクトル」などを扱うための特別なデータ構造が用意されています。Pythonでプログラムを書くくためのファーストステップとして、データ構造を深く理解することが何よりも重要となります。


Pythonが提供するデータ構造には大きく「リスト」「タプル」「辞書」の3種類があります。

図1 Pythonのデータ構造

それぞれ次のような特徴があります。

リスト(List)

[要素1, 要素2, ・・・] のように、”[]”(角カッコ)の中に要素が“,”(カンマ)区切りで並びます。リストは、ミュータブル(mutable)なデータ構造で、要素の追加・更新・削除を自由に行うことができます。

他言語の配列に近い扱い方がありますが、次のような違いがあります。

<他言語の配列との違い>
  • 要素には、さまざまなデータ型(整数、文字列など)を混在することができる
  • C言語のようにメモリアドレスを強く意識しない

リストの詳細は、こちらの記事で解説していますので参考にして下さい。


タプル(Tuple)

(要素1, 要素2, ・・・) のように、”()”(カッコ)の中に要素が“,”(カンマ)区切りで並びます。

タプルは、リストと類似していますがイミュータブルなデータ構造となります。つまり、リストのように一度定義したタプルは、要素の追加・更新・削除を行うことができません。

リストとの違いは次のようなものがあります。

<リスト(List)との違い>
  • イミュータブルで要素の追加・更新・削除ができない
  • リストよりも、生成速度が速く、メモリーの使用量が小さい

タプルの詳細は、こちらの記事で解説していますので参考にして下さい。


辞書(dictionary)

{key1:value1, key2:value2, } のように、“{}”(中カッコ)の中に、キー:値を1組とする要素が“,”(カンマ)区切りで並びます。タプルもリスト同様にミュータブル(mutable)なデータ構造で、要素の追加・更新・削除を自由に行うことができます。リストやタプルとの違いは次のようなものがあります。

<リスト(List)との違い>
  • 要素の並び順を意識することはない(キーを識別子として各要素にアクセスする)
  • 同じキーを重複してもたせることはできない(値は重複できます)。

今回は、この「辞書(dictionary)」について「データ構造の基本」から「作り方(定義方法)」「要素へのアクセス(参照・取得・更新)」「辞書型の関数」について基礎から丁寧に図解で解説をします。

この記事を読むことで次のことが「できるわかる」ようになりますので最後までお付き合い下さい。

  1. 「辞書(dictionary)」データ構造の基本と作り方(定義の仕方)
  2. 辞書の各要素へのアクセス方法(参照・取得・更新)について
  3. 辞書型が提供する標準関数やメソッドについて

本サイトでの紹介内容は一例です。また、関数などの省略可能なオプション引数などについては割愛していますので、詳細や不明点などは必要に応じて公式サイトなどを参照してください。

【Python公式ドキュメント】https://docs.python.org/ja/3/library/stdtypes.html#mapping-types-dict

スポンサーリンク

1. 辞書型(dictionary)とは

Pythonのデータ型である「辞書型」(dictionary)は、「リスト」や「タプル」と同じように複数の値を要素として管理するデータ構造の一つです。

「リスト」や「タプル」は、個々の要素を並び順(インデックス)で管理していますが、辞書の場合は、「キー(Key)」と呼ばれる識別子(ラベル)が割り振られ、個々の要素を管理します。

辞書の書式は、以下のように{}の中に、「キー(Key):値(Value)」を組合せた要素をもつ構造をとります。要素(値)へのアクセスは、キーを使って参照するので一つの辞書の中に同じキーを重複して持たせることはできません。よって、リストやタプルのように要素の位置を意識することはありません。

Python辞書の構文_rev0.2
図2 辞書オブジェクトのキーと値の関係

また「キー(Key)」は後から変更できない性質上、イミュータブルな型をもつデータを採ります。「文字列」や「数値」「タプル」などのデータがキーになり得ます。

一方、値については、イミュータブルなデータ型の他、リストや辞書といったミュータブルなデータ型を採ることができます。(図3)

Python_辞書オブジェクトの特徴_rev0.1
図3 辞書オブジェクトの基本構文

1.1. 辞書の基本操作について

辞書型のデータ構造を実際にコードで確認してみましょう。次の<List1>は基本的な辞書の作成例として、「キー」にイミュータブルなオブジェクトである、「文字列()」「数値()」「タプル()」を指定しています。問題なく辞書が作成できています。

dict1 = {'a':1, 'b':2, 'c':3}                     # キーに文字列を指定
dict2 = {10:'apple', 20:'orange', 30:'pine'}      # キーに数字を指定
dict3 = {(1, 2, 3):'apple'}                       # キーにタプル(イミュータブル)を指定


# キーは、イミュータブルなオブジェクトを指定する

print(dict1)                      # ➀ {'a': 1, 'b': 2, 'c': 3}
print(type(dict1))                # <class 'dict'>

print(dict2)                      # ➁ {10: 'apple', 20: 'orange', 30: 'pine'}
print(type(dict2))                # <class 'dict'>

print(dict3)                      # ➂ {(1, 2, 3): 'apple'}
print(type(dict3))                #  <class 'dict'>

「キー」はイミュータブルなオブジェクトを指定する

》{‘a‘: 1, ‘b‘: 2, ‘c‘: 3}

》{10: ‘apple’, 20: ‘orange’, 30: ‘pine’}

》{(1, 2, 3): ‘apple’}


今度は「キー」にミュータブルなオブジェクトである「リスト」を指定した場合の例を示します。()<List2>「キー」はイミュータブルなオブジェクトしか指定できませんので次のように「TypeErrorが発生して辞書を作成することはできません。

dict4 = {[1,2,3]:'apple'}      # キーがリスト(ミュータブル)

# キーは、ミュータブルなオブジェクトを採ることができない
print(dict4)                   # ➃ TypeError: unhashable type: 'list'

「キー」はミュータブルなオブジェクトを採ることができない

TypeError: unhashable type: ‘list’


「キー」の値が重複することは許することは許されません。例えば、次のように同じ「キー」をもつ辞書を定義しようとするとエラーになることはありませんが、最後に指定した「キー」の値が最終的にその辞書の要素となります。()

dict6 = {'a':1, 'a':2, 'b':3, 'b':4}  # キーを重複してオブジェクトをつくる

# キーを重複指定した場合は、最後に指定した値が反映される
print(dict6)                       # ➄ {'a': 2, 'b': 4}
print(type(dict6))                 # <class 'dict'>

キーを重複指定した場合は、最後に指定した値が反映される

》{‘a’: 2, ‘b’: 4}


また、辞書の要素にアクセスする(値を取得する)には、“[キー]”のようにキーをインデックスにして対となる値にアクセスします。存在しないキーに対してアクセスを試みた場合は、「KeyError」が発生します。

dict7 = { 'key1' : 1, 'key2' : 2, 'key3' : 3 }

# 値にアクセスするには、キーをインデックス指定する
print(dict7['key1'])    # ➅ 1
print(dict7['key2'])    # ➆ 2

# 存在しないキーに対してアクセスを試みるとエラーが発生する
print(dict7['key4'])    #➆ KeyError

値にアクセスするには、キーをインデックス指定する

》1

》2

存在しないキーに対してアクセスを試みるとエラーが発生する

KeyError

1.2 辞書の要素の更新と追加について

辞書は、ミュータブルなオブジェクトですので、後から要素を「更新」したり「追加」することができます。

書式は次のように「辞書オブジェクト」に”キー(key)”をインデックス指定して、”新しい値(value)”を設定することで対応します。

指定した“キー”が既に存在していれば、“新しい値”で書き換えられます。(更新)

存在していなければ、新しい要素として「“キー”:“新しい値”」が追加されることになります。

辞書オブジェクトの更新と追加

辞書オブジェクト[ キー ] = 新しい値

指定した「キー」が既に存在していれば、新しい値で書き換える(更新)

指定した「キー」が存在していなければ、新しい要素(キー:値)として(追加)する

Python辞書の追加と更新_rev0.1
図4 辞書の要素を更新・追加する

辞書の「更新」「追加」について具体例で確認します。


例1.既存の辞書オブジェクトに対して要素を更新します。<List5>

更新したい「キー」をインデックス指定して、新たな値で書き換えます。(’key1’を1→10へ更新, ’key3’を3→30へ更新しています。)

dict1 = { 'key1' : 1, 'key2' : 2, 'key3' : 3 }
print(dict1)   # ➀ {'key1': 1, 'key2': 2, 'key3': 3}


# キー(key1)の値を10に更新する
dict1['key1'] = 10
print(dict1)   # ➁ {'key1': 10, 'key2': 2, 'key3': 3}

# キー(key3)の値を30に更新する
dict1['key3'] = 30
print(dict1)   # ➂ {'key1': 10, 'key2': 2, 'key3': 30}

》{‘key1’: 1, ‘key2’: 2, ‘key3’: 3}

キー(key1)の値を10に更新された

》{‘key1’: 10, ‘key2’: 2, ‘key3’: 3}

キー(key3)の値を30に更新された

》{‘key1’: 10, ‘key2’: 2, ‘key3’: 30}


例2. 既存の辞書オブジェクトに対して要素を追加します。<List6>

追加したい、新規「キー」をインデックスに指定して、新たな値とともに新要素として追加します。

(新要素 「’key4’:40」 を追加しています。)

# キー(key4)の要素を追加する
dict1['key4'] = 40
print(dict1)   # ➃ {'key1': 10, 'key2': 2, 'key3': 30, 'key4': 40}

キー(key4)の要素を末尾に追加する

》{‘key1’: 10, ‘key2’: 2, ‘key3’: 30, ‘key4’: 40}

1.2.1 辞書の追加・更新に関するメソッド

追加と更新に関して、辞書オブジェクトには2つの関数が用意されています。

1つは setdefault()メソッド で、辞書オブジェクトに「キー」で指定した要素が存在しなければその要素を追加しますが、すでに存在した場合は置き換えません。つまり、値の上書きを防ぐことができます。

そして2つ目は update()メソッド で2つの辞書をマージし、既存の要素を更新します。書式は次のとおりです。図4 辞書の更新と追加に関するメソッド

辞書オブジェクトの<追加・更新>

辞書オブジェクト.setdefault(key, value)

引数:key:追加したい「キー」を指定する

引数:value:追加したい「値」を指定する 省略可能(省略した場合は値が‘None’の要素となる)

戻り値:現在のキーの値


辞書オブジェクト.update(dict)

引数:dict:更新用の辞書

戻り値:なし 元の辞書オブジェクト自体を更新します

Python_辞書オブジェクトの更新と追加
図5 辞書の更新と追加に関するメソッド

例1. setdefault()メソッド の使用例を示します。<List7>

次の例では、既存のキー(‘key1’)に対しては、値を更新しません (上書きしない)()が、辞書に存在しないキー(‘key4’)の場合は、新規要素が追加されます。()

また、setdefault()メソッドの第2引数を省略した場合は、値が’None’として要素が追加されます。()

dict1 = { 'key1' : 1, 'key2' : 2, 'key3' : 3 }
print(dict1)     # ➀ {'key1': 1, 'key2': 2, 'key3': 3}

# 既存のキー「キー(key1)」の場合は、更新しない
dict1.setdefault('key1', 10)
print(dict1)     # ➁ {'key1': 1, 'key2': 2, 'key3': 3}

# 存在しない「キー(key4)」の場合は、新規要素が追加される
dict1.setdefault('key4', 40)
print(dict1)     # ➂ {'key1': 1, 'key2': 2, 'key3': 3, 'key4': 40}

# setdefault()メソッドの第2引数を省略した場合は、値が'None'となる
dict1.setdefault('key5')
print(dict1)     # ➃ {'key1': 1, 'key2': 2, 'key3': 3, 'key4': 40, 'key5': None}

既存のキー「キー(key1)」の場合は、更新しない

》{‘key1’: 1, ‘key2’: 2, ‘key3’: 3}

存在しない「キー(key4)」の場合は、新規要素が追加される

》{‘key1’: 1, ‘key2’: 2, ‘key3’: 3, ‘key4’: 40}

setdefault()メソッド の第2引数を省略した場合は、値が’None’となる

》{‘key1’: 1, ‘key2’: 2, ‘key3’: 3, ‘key4’: 40, ‘key5’: None}


例2. update()メソッド の使用例を示します。<List8>

次の例では、辞書(dict1())を辞書(dict2())でアップデート(更新)します。既存のキーの値を更新し、キーが存在しない場合は要素ごと追加します。

結果は、’key1’の要素が1→10へ更新され、’key4’の要素が追加されました。()

dict1 = { 'key1' : 1, 'key2' : 2, 'key3' : 3 }
print(dict1)     # ➄ {'key1': 1, 'key2': 2, 'key3': 3}

dict2 = { 'key1' : 10, 'key4' : 40 }
print(dict2)     # ➅ {'key1': 10, 'key4': 40}

# update()メソッドで、dict1 を dict2 でアップデート(更新)する
dict1.update(dict2)
print(dict1)     # ➆ {'key1': 10, 'key2': 2, 'key3': 3, 'key4': 40}

# update()メソッドは戻り値は返しません(dict1そのものを更新します)
result = dict1.update(dict2)
print(result)     # ➇ None

》{‘key1’: 1, ‘key2’: 2, ‘key3’: 3}

》{‘key1’: 10, ‘key4’: 40}

update()メソッドで、dict1をdict2 でアップデート(更新)する

》{‘key1’: 10, ‘key2’: 2, ‘key3’: 3, ‘key4’: 40}

update()メソッドは戻り値は返しません(dict1そのものを更新します)

None

なお、update()メソッド は戻り値を返さず、元の辞書そのものを更新します。よって、のように変数resultは‘None’となります。

1.3 辞書の要素を削除する

辞書は不要になった要素を削除することができます。要素を指定して削除する「delステートメント」と一度にすべての要素を削除できる「clear()メソッド」があります。書式は以下の通りです。

要素を削除する

<指定した要素を削除する>

del 辞書オブジェクト[key]

インデクス:key: 削除する要素のキーを指定


<すべての要素を削除する>

辞書オブジェクト.clear()

引数:なし

辞書の要素を削除する具体例を紹介します。

例1. delステートメントで特定の要素を削除する。<List9>

次の例では、キー(‘key1’)とキー(’key2’)をインデックス指定して delステートメント で該当する要素を削除しています。(,)

dict1 = { 'key1' : 1, 'key2' : 2, 'key3' : 3 }
print(dict1)       # ➀ {'key1': 1, 'key2': 2, 'key3': 3}

# キー(key1)に対応する要素を削除する
del dict1['key1']
print(dict1)       # ➁ {'key2': 2, 'key3': 3}

# キー(key2)に対応する要素を削除する
del dict1['key2']
print(dict1)       # ➂ {'key3': 3}

》{‘key1’: 1, ‘key2’: 2, ‘key3’: 3}

キー(key1)に対応する要素を削除する

》{‘key2’: 2, ‘key3’: 3}

キー(key2)に対応する要素を削除する

》{‘key3’: 3}

また、存在しない「キー」に対して削除を行おうとするとエラーが発生します。次の例では削除済みのキー(‘key1’)を指定してdelステートメントを実行していますが、“KeyError”が発生しています。(➃)

# 存在しない、キーを指定して削除しようとした場合はエラーとなる
del dict1['key1']
print(diect1)       # ➃ KeyError: 'key1'

存在しない、キーを指定して削除しようとした場合はエラーとなる

KeyError


例2. 辞書オブジェクトの「clear()メソッド」を使うことで、すべての要素を一度に削除することも可能です。()

dict2 = { 'key1' : 1, 'key2' : 2, 'key3' : 3 }
print(dict2)       # ➄ {'key1': 1, 'key2': 2, 'key3': 3}

# cliear()メソッドで、全ての要素を削除する
dict2.clear()
print(dict2)       # ➅ {} 空の辞書が残る

cliear()メソッドで、全ての要素を削除する

》{}

以上が、辞書の基本操作(新規作成・要素の追加/更新)についての解説となります。次節からは、より効率的に辞書を作成することができる「dict()クラス」について解説してきます。

スポンサーリンク

2. 辞書をつくるdictクラス

Python_基本文法_内包表記

<1節>では、辞書オブジェクトは{キー(Key):値(Value)}の形式で作成することができると解説しました。Pythonには辞書を作成するための組込みクラスとして「dictクラス」が関連メソッドとともに用意されており、効率的に辞書を作成することもできます。

本節では、dictクラスの活用方法について解説します。

dictクラス

辞書(Dict)オブジェクト = dict(**kwarg)

引数:**kwarg:イテラブルなオブジェクトやキーワード引数で初期値を指定

戻り値: Dictオブジェクト

2.1 dictクラスの基本操作

dictクラス引数:**kwargには任意の数の引数を指定することができます。引数の書式は次の書式のように、イテラブルなオブジェクト(タプル、リスト、辞書※)やキーワード引数を指定して使います。「イテラブルなオブジェクト」と「キーワード引数」は組み合わせることも可能です。

Python_Dictクラスの引数指定方法_rev0.1
図6 dictクラスの引数指定の方法

それぞれの書式について、具体例で確認します。

例1. タプル(キー, 値)を要素とするリストを引数に指定するパターンです。<List12>

タプルのリストを返す、標準関数 zip() を活用すれば、2つのリストから効率的に辞書を生成することができます。()

# Dictクラスの引数に、「タプルを要素とするリスト」を設定した場合

dict1 = dict( [ ('key1', 111),  ('key2', 222),  ('key3', 333) ] )

print(dict1)          # ➀ {{'key1': 111, 'key2': 222, 'key3': 333}
print(type(dict1))    # ➁ <class 'dict'>


# zip関数で、「タプルを要素とするリスト」を生成した場合

keys = ['Key1', 'Key2', 'Key3']
vals = [111, 222, 333]

dict2 = dict(zip(keys, vals))

print(dict2)          # ➂ {'Key1': 111, 'Key2': 222, 'Key3': 333}
print(type(dict2))    # ➃ <class 'dict'>

Dictクラスの引数に「タプルを要素とするリスト」を設定した場合

》{‘key1’: 111, ‘key2’: 222, ‘key3’: 333}

》<class ‘dict>

zip関数で「タプルを要素とするリスト」を生成した場合

》{‘key1’: 111, ‘key2’: 222, ‘key3’: 333}

》<class ‘dict>


例2.リスト[キー, 値]を要素とするタプルを引数に指定するパターンです。<List13>

# Dictクラスの引数に「リストを要素とするタプルを設定した場合

dict3 = dict( ( ['key1', 111],  ['key2', 222],  ['key3', 333] ) )

print(dict3)         # ➄ {'key1': 111, 'key2': 222, 'key3': 333}
print(type(result))  # ➅ <class 'dict'>

Dictクラスの引数に「リストを要素とするタプルを設定した場合

》{‘key1’: 111, ‘key2’: 222, ‘key3’: 333}

》<class ‘dict>


例3. キーワード引数で指定するパターンです。<List14>

キーワードは、文字列で指定してはいけません。辞書を生成する際に、キーワードが文字列として「キー」に登録されます。なお、キーワードを文字列で指定した場合は「SyntaxError」が発生します。()

# Dictクラスの引数に「キー = 値」キーワード引数を設定した場合

dict4 = dict( key1 = 111,  key2 = 222,  key3 = 333 )
print(dict4)         # ➆ {'key1': 111, 'key2': 222, 'key3': 333}
print(type(dict4))   # ➇ <class 'dict'>


# キーワード引数のキーに文字列("")を設定した場合

dict5 = dict( 'key1' = 111,  'key2' = 222,  'key3' = 333 )
# ➈ SyntaxError: keyword can't be an expression

Dictクラスの引数に「キー = 値」キーワード引数を設定した場合

》{‘key1’: 111, ‘key2’: 222, ‘key3’: 333}

》<class ‘dict>

キーワード引数のキーに文字列(“”)を設定した場合

SyntaxError: keyword can’t be an expression


例4. 引数にはイテラブルなオブジェクトとキーワード引数による指定を混在させることができます。

(,)ただし、キーワード引数はを先頭に置くことはできず、「SyntaxError」が発生します。()

# Dictクラスの引数に、イテラブルなオブジェクトとキーワード引数を混在させた場合
dict6 = dict( [('key1', 111),  ('key2',  222)],  key3 = 333 )
print(dict6)    # ➈ {'key1': 111, 'key2': 222, 'key3': 333}

dict7 = dict( (['key1', 111],  ['key2',  222]),  key3 = 333 )
print(dict6)    # ➉ {'key1': 111, 'key2': 222, 'key3': 333}


# キーワード引数は、先頭に配置することはできないのでエラーが発生する
dict8 = dict( key3 = 333, [('key1', 111),  ('key2',  222)] )
print(dict8)    # ⑪ SyntaxError: positional argument follows keyword argument

Dictクラスの引数に、イテラブルなオブジェクトとキーワード引数を混在させた場合

》{‘key1’: 111, ‘key2’: 222, ‘key3’: 333}

》{‘key1’: 111, ‘key2’: 222, ‘key3’: 333}

キーワード引数は、先頭に配置することはできないのでエラーが発生する

SyntaxError: positional argument follows keyword argument

2.2 dictクラスの「fromkeys()メソッド」

dictクラス は、引数に「キー」と「値」の組合せを指定して辞書オブジェクトを生成するのでした。「dictクラス」には、「キー」のみを指定して効率的に辞書を生成できる「fromkeysメソッド」というものもあります。(値もデフォルト(初期値)値として設定できます)

「fromkeysメソッド」の書式は次の通りです。

dict.fromkeys()メソッド

dict.fromkeys(iterable, value)

引数:iterable:「キー」とするイテラブルなオブジェクト(リストやタプルなど)

引数:value:「値」の初期値を指定する ※省略可能(省略した場合は’Nane’が設定される)

戻り値: 辞書オブジェクト

「dictクラス」の「fromkeysメソッド」の使用例を紹介します。

第1 引数:iterable に「リスト」と「タプル」を指定して辞書の「キー」とする例です。引数:value には、初期値を設定します。

各オブジェクトの要素が展開されそれぞれを「キー」とし、123を初期値とする辞書が生成されました。(,)

# 引数:iterableに"リスト"を指定して、「キー」に展開した場合
dict1 = dict.fromkeys( ['key1', 'key2', 'key3'], 123 )

print(dict1)                # ➀ {'key1': 123, 'key2': 123, 'key3': 123}

# 引数:iterableに"タプル"を指定して、「キー」に展開した場合
dict2 = dict.fromkeys( ('key1', 'key2', 'key3'), 123 )

print(dict2)                # ➁ {'key1': 123, 'key2': 123, 'key3': 123}

引数:iterable に”リスト”を指定して、「キー」に展開した場合

》{‘key1’: 123, ‘key2’: 123, ‘key3’: 123}

引数:iterable“タプル”を指定して、「キー」に展開した場合

》{‘key1’: 111, ‘key2’: 222, ‘key3’: 333}


引数:iterable には「文字列」を指定することもできます。文字列が各文字に展開されて「キー」となります。次は、“ABCD”の各文字を「キー」とする、初期値なし(‘None’)とした場合の例です。()

# 引数:iterableに"文字列"を指定して、各文字を「キー」に展開する
# 引数:valueを省略した場合
dict3 = dict.fromkeys( 'ABCD' )

print(dict3)                # ➂ {'A': None, 'B': None, 'C': None, 'D': None}

引数:iterable に”文字列”を指定して、各文字を「キー」に展開する

引数:value を省略した場合は値がNoneとなる

》{‘A’: None, ‘B’: None, ‘C’: None, ‘D’: None}

スポンサーリンク

3. 辞書オブジェクトの関連メソッド

辞書オブジェクトには、要素(キーや値)を「取得する」ものであったり、「複製」や「抜き取る」といった関連メソッドがあります。本節では、辞書を使いこなす上で知っておきたい必須メソッドの活用事例を示しています。

3.1 要素(キー, 値)を取得する「keys/values/itemsメソッド

辞書の要素を取得するメソッドに「keys()メソッド」「values()メソッド」「items()メソッド」があります。それぞれ、辞書オブジェクト内のすべての「キー」「値」「要素(キー, 値)」を取得することができます。ただし、図〇のようにこれらのメソッドの戻り値は「dict_keys型」「dict_value型」「dict_item型」とやや特殊なオブジェクト型となります。

Python_辞書オブジェクトkeys_values_items
図7 keys()/values()/items()メソッド

いずれもイテラブルなオブジェクトなので、これらを単独で利用するというよりかは、通常「For文句」や「内包表記」とともに使われることが多い印象です。

<List18>のでは、「For文句」で各要素に展開していますし、➇➈では内包表記により、リスト(List)に変換しています。

dict1 = {'key1':1,'key2':2,'key3':3}


# 辞書オブジェクトの「keys()メソッド」による「キー」の取得
print(dict1.keys())            # ➀ dict_keys(['key1', 'key2', 'key3'])
print(type(dict1.keys()))      # ➁ <class 'dict_keys'>

# 辞書オブジェクトの「values()メソッド」による「値」の取得
print(dict1.values())          # ➂ dict_values([1, 2, 3])
print(type(dict1.values()))    # ➃ <class 'dict_values'>

# 辞書オブジェクトの「values()メソッド」による「値」の取得
print(dict1.items())           # ➄ dict_items([('key1', 1), ('key2', 2), ('key3', 3)])
print(type(dict1.items()))     # ➅ <class 'dict_items'>

# For文句による展開
for key, item in dict1.items():
    print(f"key: {key}, item: {item}")   # ➆

# 内包表記による展開
print([key for key, item in dict1.items() ])              # ➇ ['key1', 'key2', 'key3']
print([[key, item * 2] for key, item in dict1.items()])   # ➈ [['key1', 2], ['key2', 4], ['key3', 6]]

key: key1, item: 1
key: key2, item: 2
key: key3, item: 3

dict_keys([‘key1’, ‘key2’, ‘key3’])

dict_values([1, 2, 3])

dict_items([(‘key1’, 1), (‘key2’, 2), (‘key3’, 3)])

For文句による展開

》key: key1, item: 1

》key: key2, item: 2

》key: key3, item: 3

内包表記による展開

》[‘key1’, ‘key2’, ‘key3’]

》[[‘key1’, 2], [‘key2’, 4], [‘key3’, 6]]

なお、「dict_keys型」「dict_value型」「dict_item型」は、Pythonの標準関数である「list()」や「len()」で処理することもできます。特に「dict_value型」は「max()/min()/sum()」などといった演算処理も要素の型によっては可能です。

内包表記については、こちらの記事も参考にして下さい。

3.2 複製と要素の抜き取り(copy()/pop()/popitem())

辞書オブジェクトの複製(コピー)は「copy()メソッド」を使います。この複製は複製はいわゆる「深いコピー」のことで、メモリ上の実体(オブジェクト)ごとコピーすることを指します。このことは、複製元と複製先の辞書とは互いに干渉し合うことはありません。

図8の左図のように単なる「ラベル」の差し替えではないことに注意しましょう。

Python_辞書_要素の複製_copy_rev0.1
図8 浅いコピー(ラベルの差し替え)と深いコピー(copy()メソッド)

複製を行う copy()メソッド は次の書式のとおりで、引数はありません。

copy()メソッド

辞書オブジェクト.copy()


引数: なし

戻り値: 辞書オブジェクト 辞書を複製して、同じ要素をもった別の辞書を作成する

copy()メソッド の具体例を<List19>に示します。ポイントは「オブジェクト()」自体の複製であること「複製元と複製先とは互いに干渉しないこと(➂➃)」です。

dict1 = {'key1':1,'key2':2,'key3':3}

# 辞書オブジェクトの copy()メソッドで「深いコピー」を行う
dict2 = dict1.copy()
print(dict2)             # ➀ {'key1': 1, 'key2': 2, 'key3': 3}

# dict1 と dict2 は別のオブジェクト
print(dict1 is dict2)    # ➁ False

# 複製先の要素を変更しても、複製元の要素に影響しない。
dict2['key2'] = 10

print(dict1)      # ➂ {'key1': 1, 'key2': 2, 'key3': 3}
print(dict2)      # ➃ {'key1': 1, 'key2': 10, 'key3': 3}

辞書オブジェクトの copy()メソッド で「深いコピー」を行う

》{‘key1’: 1, ‘key2’: 2, ‘key3’: 3}

dict1 と dict2 は別のオブジェクト

》False

複製先の要素を変更しても、複製元の要素に影響しない

》{‘key1’: 1, ‘key2’: 2, ‘key3’: 3}

》{‘key1’: 1, ‘key2’: 10, ‘key3’: 3}


辞書オブジェクトから特定の要素を抜き取るには、「pop()メソッド」とpopitem()メソッド」にて行います。抜き取りは、対象要素(値)の「取得」と「削除(1.3項)」を同時に行うことを指します。

図9のように「pop()メソッド」は、抜き取る要素の「キー」を引数で指定することができます。一方「popitem()メソッド」は、つねに末尾の要素を対象に抜き取る(LIFO[Last In First Out])といった違いがあります。

Python_辞書_要素の抜き取り_pop_popitem_rev0.1
図9 pop()/popitem()メソッドの違い

両メソッドの書式は以下の通りです。「pop()メソッド」について 引数:value引数:key の要素が存在しないときに戻す値を指定することができます。

もし、指定した要素がなく 引数:value を設定していない場合は、エラー(‘KeyError’)が発生します。

pop()/popitemメソッド

<指定キーの要素を抜き取る>

辞書オブジェクト.pop(key,value) 

引数:key:抜き出したい「キー」を指定する

引数:value: 引数:key で指定した要素が存在しない場合に返す値を指定する

戻り値: 辞書を複製して、同じ要素をもった別の辞書を作成する


<末尾から要素を抜き取る>

辞書オブジェクト.popitem()

引数:なし

戻り値:末尾の要素から順番に、要素をタプル型式(キー, 値)で抜き出す

pop()メソッド」の具体例を<List21>に示します。pop()を繰り返すごとに値を取得した後に、対象の要素がオブジェクトが削除されます。(~)また 引数:key を省略することはできません。()

dict1 = {'key1':1,'key2':2,'key3':3,'key4':4 }

# 辞書オブジェクトのpop()メソッドで特定の要素を抜き取る

dict1.pop('key2') # ➄ 2
print(dict1)      # ➅ {'key1': 1, 'key3': 3, 'key4': 4}

dict1.pop('key3') # ➆ 3
print(dict1)      # ➇ {'key1': 1, 'key4': 4}


# 存在しない、要素を抜き取ろうとするとエラーが発生する
dict1.pop('key3') # ➈ KeyError 

# 引数を省略することはできない
dict1.pop()    # ➉ TypeError: pop expected at least 1 arguments, got 0

次に、「popitem()メソッド」の具体例を<List22>に示します。popitem()を繰り返すごとに、末尾の要素の値を戻し、オブジェクトから要素をさ削除となり<FILO型のスタック>動作となります。よって、のように引数を指定するとエラーが発呼されます。

dict1 = {'key1':1,'key2':2,'key3':3,'key4':4 }

# 辞書オブジェクトのpopitem()メソッドで特定の要素を抜き取る

dict1.popitem()    # ⑪ ('key4', 4)
dict1.popitem()    # ⑫ ('key3', 3)

print(dict1)     # ⑬ {'key1': 1, 'key2': 2}

# 引数を指定することはできない
dict1.popitem('key1')    # ⑭ TypeError: popitem() takes no arguments (1 given)

以上、辞書オブジェクトの関連メソッドとして、よく使われるものを厳選して紹介しました。これ以外にも、「get()メソッド」や「reversed()関数」などの機能が提供されていますので確認してみてください。

4. まとめ

いかがでしたでしょうか。

今回は、Pythonのデータ構造の一つである「辞書(dict)」について、「基本操作」から「各種メソッド(関数)の使い方」について解説をしてきました。最後に記事内容を整理しておきたいと思います。


辞書は、「リスト」とともにPythonではよく使われるデータ構図ですが、リストとは次の点で違いや特徴があります。

  • キーと値の組合わせ({キー:値, …})で一つの要素を形成する
  • 要素の並び順を意識することはない(キーを識別子として各要素にアクセスする)
  • 同じキーを重複してもたせることはできない(値は重複できる)

このことは、他言語(特にC言語)で強く意識する必要があるアドレス空間(ポインタ)」をもたないPythonにとって、「キー」の指定により、配列要素(※)にアクセスすることができる「辞書(連想配列)」はその代用となり得えます。※厳密には、配列ではありません。

また、機械学習で使われることが多いPythonにとって学習(教師)データを、正解ラベルとともに管理できる「辞書」のようなデータ構造はとりわけよく使われます

是非、今回の記事をお役立てくださいますと幸いです。

最後までお読みいただきありがとうございました。

タイトルとURLをコピーしました