辞書のkeys/values/itemsメソッドを使ってビューオブジェクトを取得して、キーや値、それらの組を反復したり、特定のキーや値が辞書に含まれているかを確認したりする方法を紹介する。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
d = {'key0': 0, 'key1': 1, 'key2': 2}
# キーを反復
keys = d.keys()
print(keys) # dict_keys(['key0', 'key1', 'key2'])
for key in keys:
print(key) # 'key0'、'key1'、'key2'が反復される
# 値を反復
values = d.values()
print(values) # dict_values([0, 1, 2])
for value in values:
print(value) # 0、1、2が反復される
# キーと値を反復
items = d.items()
print(items) # dict_items([('key0', 0), ('key1', 1), ('key2', 2)])
for key, value in items:
print(key, ':', value) # 「key0 : 0」「key1 : 1」「key2 : 2」
# キーの存在確認
existence = 'key4' in d.keys()
print(existence) # False
existence = 'key1' in d
print(existence) # True
# 値の存在確認
existence = 0 in d.values()
print(existence) # True
existence = 0 in d
print(existence) # False
# キー/値の組の存在確認
existence = ('key0', 0) in d.items()
print(existence) # True
existence = ('key0', 1) in d.items()
print(existence) # False
# ビューオブジェクトは動的
keys = d.keys()
print(keys) # dict_keys(['key0', 'key1', 'key2'])
d['key3'] = 3
print(keys) # dict_keys(['key0', 'key1', 'key2', 'key3'])
# キーは集合的な演算も可能
d2 = {'key0': 0, 'key1': 1, 'key2': 2}
print(d2) # {'key0': 0, 'key1': 1, 'key2': 2}
keys2 = d2.keys()
print(keys2) # dict_keys(['key0', 'key1', 'key2'])
print(keys) # dict_keys(['key0', 'key1', 'key2', 'key3'])
result = keys > keys2 # keysはkey2を包含している
print(result) # True
result = keys ^ keys2 # keysとkeys2の対象差を計算
print(result) # {'keys3'}
result = d > d2 # TypeError
result = d ^ d2 # TypeError
辞書からは「辞書ビューオブジェクト」と呼ばれるオブジェクトを取得できる。これらを使って、キー/値/キーと値を要素とするタプルを反復できる。辞書ビューオブジェクトを得るには以下のメソッドを呼び出す。
取得したビューを使うと、上記メソッドで得られる要素(キー、値、それらを要素とするタプル)を反復したり、存在確認をしたりできる。
キーや値、それらを要素とするタプルを反復するには、上で述べた通り、keys/values/itemsメソッドを使用する。以下に例を示す。
d = {'key0': 0, 'key1': 1, 'key2': 2}
# キーを反復
keys = d.keys()
print(keys) # dict_keys(['key0', 'key1', 'key2'])
for key in keys:
print(key) # 'key0'、'key1'、'key2'が反復される
この例ではkeysメソッドを用いて、キーのビューオブジェクトを取得している(dict_keysオブジェクト)。反復処理をサポートしているので、後はfor文でその値(キー)を取り出すだけだ。なお、インデックスやスライスによる特定要素の取り出しはサポートされない。
値やキー/値のタプルの反復についても同様だ。以下に例を示す。
# 値を反復
values = d.values()
print(values) # dict_values([0, 1, 2])
for value in values:
print(value) # 0、1、2が反復される
# キーと値を反復
items = d.items()
print(items) # dict_items([('key0', 0), ('key1', 1), ('key2', 2)])
for key, value in items:
print(key, ':', value) # 「key0 : 0」「key1 : 1」「key2 : 2」
itemsメソッドでは「(キー, 値)」というタプルの形で辞書の要素が格納されることは覚えておこう。
辞書ビューオブジェクトはin演算子/not in演算子を使って、そのオブジェクトに特定の値が含まれているかを確認できる。以下に例を示す。
existence = 'key4' in d.keys()
print(existence) # False
ここで例としている辞書dは「{'key0': 0, 'key1': 1, 'key2': 2}」となっているので、'key4'というキーは含まれていない。そのため、上の「'key4' in d.keys()」はFalseとなる。
なお、キーに関していえば、keysメソッドでキーのビューオブジェクトを取得しなくても、以下のように辞書に対してin演算子やnot in演算子を適用しても特定のキーの存在確認を行える。
existence = 'key1' in d
print(existence) # True
特定の値が辞書に含まれているかや、特定のキー/値の組が辞書に含まれているかを確認したいときにはビューオブジェクトを取得する必要があるので注意されたい。
以下は値の存在確認をする例だ。
existence = 0 in d.values()
print(existence) # True
辞書の値には「0」があるので、上の「0 in d.values()」はTrueとなる。しかし、何かの値が辞書に含まれているかを知るために、in演算子を辞書に直接適用するのは上で述べたように間違いだ。
existence = 0 in d
print(existence) # False
辞書の値として「0」があるかを調べようとして、上の例では「0 in d」としているが、これは辞書のキーに対する存在確認となるので、その結果はFalseとなる。
これはキー/値の組(ここではタプル)でも同様だ。以下に例を示す。
existence = ('key0', 0) in d.items()
print(existence) # True
existence = ('key0', 1) in d.items()
print(existence) # False
ビューオブジェクトは、それを取得した時点での辞書の状態を表す静的なものではなく、対象となる辞書の現在の状態を表す動的なものであることには注意しよう。
keys = d.keys()
print(keys) # dict_keys(['key0', 'key1', 'key2'])
d['key3'] = 3
print(keys) # dict_keys(['key0', 'key1', 'key2', 'key3'])
この例では、辞書dに含まれているキーを表すビューオブジェクトを取得して、その状態を表示した後に、辞書に新しいキー「'key3'」とその値「3」を追加している。そして、その前に取得したキーのビューオブジェクトの内容を表示しているが、新しい辞書の状態がビューオブジェクトに反映されていることが分かる。
これは値のビューオブジェクト、キー/値のビューオブジェクトでも同様だ。
辞書のキーには「辞書内でユニークであり、かつハッシュ可能」という特徴がある。このため、辞書のキーを集めたキーのビューオブジェクトは集合(Pythonのsetオブジェクト)と同様であり、集合の抽象基底クラスであるcollections.abc.Setで定義されている操作を適用できる。
例えば、これまでに見てきた辞書dに加えて、次のような辞書d2があったとする。
d2 = {'key0': 0, 'key1': 1, 'key2': 2}
print(d2) # {'key0': 0, 'key1': 1, 'key2': 2}
keys2 = d2.keys()
print(keys2) # dict_keys(['key0', 'key1', 'key2'])
print(keys) # dict_keys(['key0', 'key1', 'key2', 'key3'])
辞書dに対するキーのビューオブジェクトkeysは「dict_keys(['key0', 'key1', 'key2', 'key3'])」で、辞書d2のキーのビューオブジェクトkeys2は「dict_keys(['key0', 'key1', 'key2'])」である。keysとkeys2とでは、keysに'key3'があること以外は同じである。そのため、keysはkeys2を包含しているといえる。
このことは、集合演算でサポートされている>演算子で調べられる。
result = keys > keys2 # keysはkey2を包含している
print(result) # True
同様に、keysとkeys2の対象差は^演算子で求められる。
result = keys ^ keys2 # keysとkeys2の対象差を計算
print(result) # {'keys3'}
なお、「keys |= {'key100'}」のような操作を行うと、keysは上書きされてビューオブジェクトではなくなってしまうことには注意されたい(単なるsetオブジェクトとなる)。
辞書自体を対象としてこうした演算を行うことはサポートされない。
result = d > d2 # TypeError
result = d ^ d2 # TypeError
キーの存在確認は辞書自体を対象としても行えるが、キーを対象として集合的な演算を行うにはキーのビューオブジェクトが必要になることは覚えておこう(そういう状況はそうそうないかもしれないが)。
Copyright© Digital Advantage Corp. All Rights Reserved.