5.5 Python標準ライブラリ
- Pythonには様々な」役に立つ仕事をしてくれるモジュールを集めた大規模な標準ライブラリがある。
5.5.1 setdefault()とdefaultdict()による存在しないキーの処理
- 存在しないキーで辞書にアクセスしようとすると例外が生成される。辞書のget()関数を使って、キーが存在しない場合はデフォルト値を返すようにすれば例外を避けられる。
- setdefault()関数はget()と似ているがキーがなければ更に辞書に要素を追加するところが異なる。
- defaultdict()関数は存在しない全てのキーに対してデフォルトの値を設定するところがget()と異なる。**引数は関数である。**また、存在しないキーを用いた場合、そのキーが自動で生成される。デフォルト値引数を省略するとデフォルト値はNoneになる。
>>> periodic_table={"Hydrogen":1,"Helium":2}
>>> print(periodic_table)
{'Hydrogen': 1, 'Helium': 2}
# キーが辞書になければ新しい値と共に追加される。
>>> carbon=periodic_table.setdefault("Carbon",12)
>>> carbon
12
# 既存のキーに別のデフォルト値を代入しようとしても元の値が返され、辞書は変更されない。
>>> helium=periodic_table.setdefault("Helium",457)
>>> helium
2
>>> print(periodic_table)
{'Hydrogen': 1, 'Helium': 2, 'Carbon': 12}
# モジュールcollectionsからdefaultdictをインポート。
>>> from collections import defaultdict
# 存在しないキーに対するデフォルトの値(int)が設定される。
>>> periodic_table=defaultdict(int)
>>> periodic_table["Hydrogen"]=1
# 存在しないキーに対してデフォルト値が返される。
>>> periodic_table["Lead"]
0
>>> periodic_table
defaultdict(<class 'int'>, {'Hydrogen': 1, 'Lead': 0})
# モジュールcollectionsからdefaultdictをインポート
>>> from collections import defaultdict
>>>
>>> def no_idea():
... return "Huh?"
...
>>> bestiary = defaultdict(no_idea)
>>> bestiary["a"]= "A"
>>> bestiary["b"]= "B"
>>> bestiary["a"]
'A'
>>> bestiary["b"]
'B'
# 存在しないキーを入力するとdefaultdictの引数で指定された関数を呼び出し値を返す。
>>> bestiary["c"]
'Huh?'
>>> bestiary["v"]
'Huh?'
# defaultdict()呼び出しの中でデフォルト作成関数を定義
>>> bestiary=defaultdict(lambda:"Huh?")
>>> bestiary["E"]
'Huh?'
# intは独自カウンタを作るための手段になり得る。
>>> from collections import defaultdict
>>> food_counter=defaultdict(int)
>>> for food in ["spam","spam","eggs","spam"]:
... food_counter[food]+=1
...
>>> for food,count in food_counter.items():
... print(food,count)
...
spam 3
eggs 1
5.5.2 Counter()による要素数の計算
>>> breakfast=["spam","spam","eggs","spam"]
>>> breakfast_counter=Counter(breakfast)
>>> breakfast_counter
Counter({'spam': 3, 'eggs': 1})
# most_common()関数は全ての要素を降順で返す。
>>> breakfast_counter.most_common()
[('spam', 3), ('eggs', 1)]
# most_common()関数は引数として整数を指定すると最上位から数えてその個数分だけ表示する。
>>> breakfast_counter.most_common(1)
[('spam', 3)]
>>> breakfast_counter
Counter({'spam': 3, 'eggs': 1})
>>> lunch=["eggs","eggs","bacon"]
>>> lunch_counter=Counter(lunch)
>>> lunch_counter
Counter({'eggs': 2, 'bacon': 1})
# カウンタの結合
>>> lunch_counter+breakfast_counter
Counter({'eggs': 3, 'spam': 3, 'bacon': 1})
# カウンタの差 昼食では使われているが朝食では使われていないもの。
>>> lunch_counter-breakfast_counter
Counter({'eggs': 1, 'bacon': 1})
# カウンタの差 朝食では使われているが昼食では使われていないもの。
>>> breakfast_counter-lunch_counter
Counter({'spam': 3})
# 積集合演算子 共通の個数は1。
>>> breakfast_counter & lunch_counter
Counter({'eggs': 1})
# 和集合演算子 大きい方ほカウンタ値を使う。
>>> breakfast_counter | lunch_counter
Counter({'spam': 3, 'eggs': 2, 'bacon': 1})
5.5.3 OrderdDict()によるキー順のソート
- OrderedDict()はイテレータから同じ順序でキーを返す。
>>> quotes={
... "M":"A",
... "L":"O",
... "C":"N",
... }
>>> for s in quotes:
... print(s)
...
M
L
C
>>> from collections import OrderedDict
>>> quotes=OrderedDict([
... ("M","A"),
... ("L","C"),
... ("C","N"),
... ])
>>>
5.5.4 スタック+キュー=デック
- duque(デック)は両端キューのことでスタックとキューの両方の機能を持っており、シーケンスのどちらの端でも要素を追加、削除できる。
>>> def palindrome(word):
... from collections import deque
... dq=deque(word)
... while len(dq)>1:
# popleft()は左端の要素を削除して返す、pop()は右端の要素を削除して返す関数。
... if dq.popleft()!=dq.pop():
... return False
... return True
...
>>> palindrome("a")
True
>>> palindrome(" ")
True
>>> palindrome("racecar")
True
>>> palindrome("halibut")
False
# 逆順の文字列を比較した方が簡単。
>>> def another_palindrome(word):
... return word==word[::-1]
...
>>> another_palindrome("racecar")
True
>>> another_palindrome("halibut")
False
5.5.5 itertoolsによるコード構造の反復処理
- itertoolsには特別な目的を持つイテレータ関数が含まれている。
# chain()は、引数全体が一つのイテラブルであるかのように扱い、その中で反復処理を行う。
>>> import itertools
>>> for item in itertools.chain([1,2],["a","b"]):
... print(item)
...
1
2
a
b
# cycle()は無限反復子で、引数から循環的に要素を返す。
>>> import itertools
>>> for item in itertools.cycle([1,2]):
... print(item)
...
1
2
1
2
1
2
1
2
1
2
1
2
1
2
# accumulate()は要素を一つにまとめた値を計算する。デフォルトでは和を計算する。
>>> import itertools
>>> for item in itertools.accumulate([1,2,3,4]):
... print(item)
...
1
3
6
10
## accumulate()は第二引数として関数を受け付け、この引数が加算の代わりに使われる。
>>> import itertools
>>> def multiply(a,b):
... return a*b
...
>>> for item in itertools.accumulate([1,2,3,4],multiply):
... print(item)
...
1
2
6
24
5.5.6 pprint()による綺麗な表示
- print()は読みやすくするために要素の位置を揃えようとする。
>>> from pprint import pprint
>>> q=OrderedDict([
... ("Moe","A wise guy,huh?"),
... ("Larry","Ow!"),
... ("Curly","Nuyk nyuk!"),
... ])
>>>
# 続けて表示する。
>>> print(q)
OrderedDict([('Moe', 'A wise guy,huh?'), ('Larry', 'Ow!'), ('Curly', 'Nuyk nyuk!')])
# 要素の位置を揃えて表示する。
>>> pprint(q)
OrderedDict([('Moe', 'A wise guy,huh?'),
('Larry', 'Ow!'),
('Curly', 'Nuyk nyuk!')])
5.7 復習課題
5-1 zoo.pyというファイルを作り、その中にOpen 9-5 dailyという文字列を表示する。hours()関数を定義しよう。次に対話型インタープリタでzooモジュールをインポートし、そのhours()関数を呼び出そう。
zop.py
def hours():
print("Open 9-5 daily")
結果
>>> import zoo
>>> zoo.hours()
Open 9-5 daily
5-2 対話型インタープリタの中でzooモジュールをmenagerieという名前でインポートし、そのhours()関数を呼び出そう。
# モジュールzooをmenagerieとしてインポート
>>> import zoo as menagerie
>>> menagerie.hours()
Open 9-5 daily
5-3 対話型インタープリタにそのまま残り、zooのhours()関数を直接インポートして呼び出そう。
>>> from zoo import hours
>>> hours()
Open 9-5 daily
5-4 hours()関数をinfoという名前でインポートし、呼び出そう。
>>> from zoo import hours as info
>>> info()
Open 9-5 daily
5-5 "a":1,"b":2,"c":3というキー/値ペアを使ってplainという辞書を作り、内容を表示しよう。
>>> plain={"a":1,"b":2,"c":3}
>>> plain
{'a': 1, 'b': 2, 'c': 3}
5-6 上の5-5と同じペアからfancyという名前のOrderdDictを作り、内容を表示しよう。plainと同じ順序で表示されただろうか。
>>> from collections import OrderedDict
>>> fancy=OrderedDict([("a",1),("b",2),("c",3)])
>>> fancy
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
5-7 dict_of_listsという名前のdefaultdictを作り、list引数を渡そう。次に、一度の操作でdict_of_lists["a"]というリストを作り、"something for a"という値を追加しよう。最後に、dict_of_lists["a"]を表示しよう。
>>> from collections import defaultdict
>>> dict_of_lists=defaultdict(list)
>>> dict_of_lists["a"]=["something for a"]
>>> dict_of_lists["a"]
['something for a']
感想
遂に後半戦突入しました。6章やり始めたんですが、オブジェクトとクラスの概念が出てきました。
明日も引き続き頑張ります。
参考文献
「Bill Lubanovic著 『入門 Python3』(オライリージャパン発行)」