今さらPython3 (36) - 標準ライブラリの続き

第5章後半を一気に駆け抜けとく。

入門 Python 3

入門 Python 3

便利な標準ライブラリの紹介が続いております。

>>> from collections import Counter
>>> breakfast = ['spam', 'spam', 'eggs', 'spam']
>>> breakfast_counter = Counter(breakfast)
>>> breakfast_counter
Counter({'spam': 3, 'eggs': 1})

collectionsの中にあるCounterを使って出現回数をカウントしてます。昨日の記事の最後の例はなんだったんだろうw

>>> breakfast_counter.most_common()
[('spam', 3), ('eggs', 1)]
>>> breakfast_counter.most_common(1)
[('spam', 3)]
>>>
>>> breakfast_counter.most_common(2)
[('spam', 3), ('eggs', 1)] 

most_common()はCounterオブジェクトの要素を降順で返すということだね。引数を渡すとTop Nのタプルが返ってくる。

>>> breakfast_counter
Counter({'spam': 3, 'eggs': 1})
>>> lunc = ['eggs', 'eggs', 'bacon']
>>> lunch = lunc.copy()
>>> lunch_counter = Counter(lunch)
>>> lunch_counter
Counter({'eggs': 2, 'bacon': 1})

まずは、lunchとlunch_counterを用意。ここからいろいろいじるわけですね。

>>> breakfast_counter + lunch_counter
Counter({'spam': 3, 'eggs': 3, 'bacon': 1})
>>> breakfast_counter - lunch_counter
Counter({'spam': 3})
>>> lunch_counter - breakfast_counter 
Counter({'bacon': 1, 'eggs': 1})
>>> breakfast_counter & lunch_counter
Counter({'eggs': 1})
>>> breakfast_counter | lunch_counter
Counter({'spam': 3, 'eggs': 2, 'bacon': 1})
>>> 

積集合でeggsが1になるのは理解できるけど、和集合では2になるのはどう考えれば良いんだろう?実際には+を使えばいいとして、どういうケースで、この結果が欲しいのかが今のところイメージできない。

キーでソートしてくれる辞書

>>> quotes = {
...     'Moe': 'A wise guy, huh?',
...     'Larry': 'Ow!',
...     'Curly': 'Nyuk nyuk!',
...     }
>>> for stooge in quotes:
...     print(stooge)
... 
Moe
Larry
Curly
>>> 

こういう時に限って、キー順で返ってくるwでも、辞書を表示させるときに順番が守られないことは、経験上分かっております。そこで、OrderdDict()に登場願うわけですね。

>>> from collections import OrderedDict
>>> quotes = OrderedDict([
...     ('Moe', 'A wise guy, huh?'),
...     ('Larry', 'Ow'),
...     ('Curly', 'Nyuk nyuk!'),
... ])
>>> for stooge in quotes:
...     print(stooge)
... 
Moe
Larry
Curly
>>> 

はい、順番通り出てきましたね。というのは分かる。ただ、見た感じというか、書式からするとタプルが入ったリストを作っているだけのような。。。

OrderedDict([('Moe', 'A wise guy, huh?'), ('Larry', 'Ow'), ('Curly', 'Nyuk nyuk!')])
>>> 
>>> quotes['Moe']
'A wise guy, huh?'
>>> quotes['Larry']
'Ow'
>>> quotes

リストなら登録順が保持されるわな。とは言え、Dictと同じようにキーを指定すると値が出てくるところが辞書っぽい動きなんだね。

デキューじゃなくて、デック

deque--勝手にデキューと呼んでいたけど、よく考えればdequeueでやっとデキューと発音できるわけだから、デックと発音すべきだね。

>>> def palindrome(word):
...     from collections import deque
...     dq = deque(word)
...     while len(dq) > 1:
...         if dq.popleft() != dq.pop():
...              return False
...     return True
... 
>>> palindrome('a')
True
>>> palindrome('racecar')
True
>>> palindrome('')
True
>>> palindrome('radar')
True
>>> palindrome('falibut')
False
>>> palindrome('しんぶんし')
True
>>> 

ほんと日本語の扱いが楽になったなという隔世の感があったり。てか、これだと使い方がよく分からないので、少し実験。pop()とpopleft()があると。

>>> from collections import deque
>>> word = 'abcdefghijklmnopqrstuvwxyz'
>>> dq = deque(word)
>>> dq.popleft()
'a'
>>> dq.popleft(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: popleft() takes no arguments (1 given)
>>> dq.popleft()
'b'
>>> dq.pop()
'z'
>>> dq.pop()
'y'
>>> dq
deque(['c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x'])
>>> 

popleft()/pop()は引数を取らないとか、あとは先頭から行くか、最後から行くかというあたりかな。比較の意味で通常のpop()も復習。

>>> waiting = ['A', 'B', 'C', 'D']
>>> waiting.pop()
'D'
>>> waiting.pop(2)
'C'
>>> waiting
['A', 'B']

pop()のときは引数にインデックスを取るんだったね。

>>> def another_palindrome(word):
...     return word == word[::-1]
... 
>>> another_palindrome('radar')
True
>>> another_palindrome('しんぶんし')
True
>>> another_palindrome('hailbut')
False
>>> 

回文チェックは、こっちの方が簡単というお話。

(つづく)