Remrinのpython攻略日記

python3に入門しました。python3についてあれこれとサンプルコードとか。

pythonのdict型

・辞書型。マッピング型とも言う。
・シーケンスに似ているが、順序なし。
・key:valueのセットで辞書登録。key…識別子。indexがわりに使う。
・keyでも、valueでも、key:valueでもiteration可能。
・keyはimmutable(数値、タプル、文字列など)だが、valueはmutable
・print()で出力しても、登録順序で表示されるとは限らない。
・サイズ取得はlen()
 

辞書の生成

d1 = {"a":70, "b":30}
print(d1)             #{'a': 70, 'b': 30}

d2 = {}
print(d2)             #{}   空の辞書

list1 = [("x", 2), ("y", 4)]
d3 = dict(list1)      #リストやタプルから辞書を生成する関数
print(d3)             #{'y': 4, 'x': 2}

 

要素へのアクセス

 indexの代わりにkeyで指定

d1 = {"a":70, "b":30}
#print(d1[0])         #KeyError: 0   index指定はできない
print(d1["a"])        #70
#print(d1["c"])       #KeyError: 'c'    存在しないkeyだとKeyError

 

要素の追加

d1["c"] = 60          #現時点で存在していないkeyを使う。
print(d1)             #{'a': 70, 'b': 30, 'c': 60}

d1.setdefault("d", 0) #値がないときのみ追加
print(d1)             #{'d': 0, 'a': 70, 'b': 30, 'c': 60}

d3.setdefault("x", 0) #すでに存在するkeyだと追加されない。エラーも出ない。
print(d3)             #{'y': 4, 'x': 2}

 

辞書の連結

d5 = {"blue":"0x0000ff", "red":"0xff0000"} #同じkeyがあるときは上書き
d5.update({"yellow":"0xffff00", "red":"red"})
print(d5)  #{'yellow': '0xffff00', 'blue': '0x0000ff', 'red': 'red'}

d1 = {"a":1, "b":2}
d2 = {"c":3, "d":4}
d3 = dict(d1, **d2) #辞書2つまで
print(d3)           #{'d': 4, 'a': 1, 'b': 2, 'c': 3}

d1 = {"a":1, "b":2}
d2 = {"c":3, "d":4}
d3 = {"e":5, "f":6}         
d4 = {**d1, **d2, **d3}   #辞書3つ以上でも連結できる
print(d4) #{'f': 6, 'b': 2, 'c': 3, 'd': 4, 'a': 1, 'e': 5}

 

削除

d1 = {"a":70, "b":30}
del d1["a"]
print(d1)              #{'b':30}

d1 = {"a":70, "b":30}
temp = d1.pop("a")     #指定されたkey:valueを削除し、valueのみを得る
print(d1)       
print(temp)            #valueのみ

d1 = {"a":70, "b":30}
temp = d1.popitem()    #ランダムに削除し、key:valueをタプルで得る
print(d1)              #{'b':30} 
print(temp)            #('a', 70)

 

全削除

d1 = {"a":70, "b":30}
d1.clear()             #要素を全削除
print(d1)              #{}

d1 = {"a":70, "b":30}
del d1                 #d1そのものをメモリから削除
#print(d1)             #NameError: name 'd1' is not defined

d1 = {"a":70, "b":30}
while d1:              #辞書d1が空になるまで
    temp = d1.popitem()#要素を削除していく
print(d1)              #{}
print(temp)            #('a', 70)      
      
d1 = {"a":70, "b":30}
#for i in d1:
#    temp = d1.popitem() #RuntimeError: dictionary changed size during iteration

 

検索

in演算子 keyが含まれればTrue
not in演算子 keyが含まれていなければTrue
get()メソッド d1.get(“~”) 存在しないときの戻り値を設定できる

has_key()メソッド → python3で廃止
 

d1 = {"a":70, "b":30}
print("a" in d1)     #True
print("c" in d1)     #False
print("a" not in d1) #False
print("c" not in d1) #True

#d1.has_key()  "AttributeError: 'dict' object has no attribute 'has_key'

x = d1.get("a")
print(x)             #70

x = d1.get("c")
print(x)             #None

x = d1.get("c", "doesn't extist") #存在しないときの返り値を設定できる
print(x)             #doesn't exist  

 

イテレーション(リストアップ)

.keys() key の一覧(イテレータ)を返す
.values() valueの一覧
.items() (key, value)というタプルの一覧

iterkeys() →python3廃止
iteritems() →python3廃止

 

keyだけをイテレート for k in dict1: またはfor k in dict1.keys():
valueだけをイテレート for k in dict1.values():
key, valueをイテレート for k, v in dict1.items():

 

d1 = {"a":70, "b":30}
print(d1.keys())         #dict_keys(['a', 'b'])
print(d1.values())       #dict_values([70, 30])
print(d1.items())        #dict_items([('a', 70), ('b', 30)])

print(list(d1.keys()))   #['a', 'b']
print(list(d1.values())) #[70, 30]
print(list(d1.items()))  #[('a', 70), ('b', 30)]

 
○**dictの形で辞書を展開してキーワード引数を渡せる。

def distance(x, y, z):                 #原点からの距離を計算する関数
    return (x**2 + y**2 + z**2) ** 0.5
d1 = {"x":1, "y":2, "z":2}             #座標を辞書で書く
a = distance(**d1)                     #展開してから引数を渡す
print(a)                               #3.0

 

辞書型の最大値、最小値

d1 = {1:70, 2:100, 3:50, 4:80}

#keyの最大値・最小値
print(min(d1))    #1
print(max(d1))    #4

#valueの最大値・最小値
print(min(d1[x] for x in d1))    #50
print(max(d1[x] for x in d1))    #100

#valueで最大・最小を調べ、そのkeyを得る
print(min(d1, key=lambda x:d1[x]))  #3
print(max(d1, key=lambda x:d1[x]))  #2

#keyの最大値・最小値を調べ、そのvalueを得る
print(d1[min(d1)])   #70
print(d1[max(d1)])   #80

 

辞書のkeyとvalueを入れ替える

dic1 = {"睦月":"1月", "如月":"2月", "弥生":"3月"}
dic2 = {v:k for k, v in dic1.items()}

print(dic1) # {'如月': '2月', '睦月': '1月', '弥生': '3月'}
print(dic2) # {'1月': '睦月', '2月': '如月', '3月': '弥生'}

 
○辞書dictの利用例(1)
文字列に使われているひらがなをカウントする
 
辞書型を参照するときの注意
 代入するときはキーが存在してもしなくても動く。
 参照するときはキーが存在していないとKeyErrorが発生するので、あらかじめin演算子などで存在確認をする。

# -*- coding: utf-8 -*-

text = "あかねさす むらさきのゆき しめのゆき のもりはみずや きみがそでふる"
text = text.replace(" ", "")

d = {}
for ch in text:
    if ch in d:
        d[ch] += 1
    else:
        d[ch] = 1
print(d)  #{'き': 4, 'そ': 1, 'や': 1, 'る': 1, 'ず': 1, 'ふ': 1, 'も': 1, 'り': 1, 'さ': 2, 'ら': 1, 'し': 1, 'の': 3, 'み': 2, 'は': 1, 'で': 1, 'が': 1, 'す': 1, 'む': 1, 'め': 1, 'ね': 1, 'ゆ': 2, 'か': 1, 'あ': 1}

 
dict.get()メソッドのデフォルト値を使うと条件分岐なしでシンプルに書ける。

# -*- coding: utf-8 -*-

text = "あかねさす むらさきのゆき しめのゆき のもりはみずや きみがそでふる"
text = text.replace(" ", "")

d = {}
for ch in text:
    d[ch] = d.get(ch, 0) + 1

#すべてを表示すると多すぎるので、今回は最頻出のみを表示
m = max(d, key=lambda x:d[x])
print(m, d[m])  #き 4

 
collectionのCounterを使うとシンプルに最頻値を調べられる。

from collections import Counter
c = Counter(text)
print(c.most_common(1))   #[('き', 4)]

 
アミノ酸のコドン表の辞書を作る。

bases = "UCAG"
codons = [b1+b2+b3 for b1 in bases for b2 in bases for b3 in bases]
aminoacids = "FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG"
codon_dict = dict(zip(codons, aminoacids))
print(codon_dict)

 

codon_dict={
'UUU':'F',  'UUC':'F',  'UUA':'L',  'UUG':'L',  
'UCU':'S',  'UCC':'S',  'UCA':'S',  'UCG':'S',  
'UAU':'Y',  'UAC':'Y',  'UAA':'*',  'UAG':'*',  
'UGU':'C',  'UGC':'C',  'UGA':'*',  'UGG':'W',  
'CUU':'L',  'CUC':'L',  'CUA':'L',  'CUG':'L',  
'CCU':'P',  'CCC':'P',  'CCA':'P',  'CCG':'P',  
'CAU':'H',  'CAC':'H',  'CAA':'Q',  'CAG':'Q',  
'CGU':'R',  'CGC':'R',  'CGA':'R',  'CGG':'R',  
'AUU':'I',  'AUC':'I',  'AUA':'I',  'AUG':'M',  
'ACU':'T',  'ACC':'T',  'ACA':'T',  'ACG':'T',  
'AAU':'N',  'AAC':'N',  'AAA':'K',  'AAG':'K',  
'AGU':'S',  'AGC':'S',  'AGA':'R',  'AGG':'R',  
'GUU':'V',  'GUC':'V',  'GUA':'V',  'GUG':'V',  
'GCU':'A',  'GCC':'A',  'GCA':'A',  'GCG':'A',  
'GAU':'D',  'GAC':'D',  'GAA':'E',  'GAG':'E',  
'GGU':'G',  'GGC':'G',  'GGA':'G',  'GGG':'G'}

 

dictクラスの継承

インタラクティブシェルでhelp(dict)とすると、メソッド一覧がある。
書き換えたいメソッドだけ上書きするとオリジナルのクラスが作れる。

# dictクラスを継承し、str型のみキーとして受け取れる辞書クラスを作る
class StrDict(dict):                    
    # 書き換えたいメソッドのみを上書きする。
    def __setitem__(self, key, value):
        if not isinstance(key, str):
            raise ValueError("Key must be str.")
        super().__setitem__(key, value)
        
d1 = StrDict()
d1["red"] = "0xFF0000"
print(d1["red"])

#d1[0] = 0  # ValueError: Key must be str.

クラスに継承についてはこちら