毎日Learning

学んだことを共有します

エキスパート Python プログラミング メモ Vol.1

エキスパートPythonプログラミング を読むので、読んだ内容の理解を深めるため、メモ的に内容を残すことをしようと思う。

第1章「さあ、はじめよう」は、インストールやらエディタについて色々書いてあるが、ほとんど知ってるし割愛。

第2章「構文ベストプラクティスークラス以外」

本章では現代的な構文のうち、もっとも重要な要素と、それらの使用方法におけるTipsを説明します。

●リスト内包表記
イテレータとジェネレータ
●デコレータ
●with と contextlib

ですって。超ワクワク。

2.1 リスト内包表記

言うまでもありませんが、次のようなコードはエレガントではありません。

>>> size = 10
>>> L = []
>>> i = 0
>>> while i < size:
...     if i % 2 == 0 and i != 4:
...         L.append(i)
...     i += 1
>>> L
[0, 2, 6, 8]

この書き方はC言語で良いかもしれませんが、次の理由のために、Pythonでは遅くなります。

●リストを操作するコードをループ毎にインタプリタ上で処理する必要がある。
●カウンタの操作もループ毎にインタプリタ上で処理する必要がある。

このパターンのコードを書く場合には、リスト内包表記を使用するべきです。リスト内包表記を利用すると、先ほどの構文が行っていた処理の一部がインタプリタ内部で実行されるようになるので、処理が速くなります。

ふむふむ。リストに要素をappend()する場合、インタプリタは「リストからappend属性を取り出してそれを関数として呼び出す」という処理をするが、内包表記やと「リストに要素を追加する」という処理になるのか。
だから速いのか。わっかりやすー。

で、コードは、

>>> [i for i in range(10) if i % 2 == 0 and i != 4]
[0, 2, 6, 8]

っていうか、速度もそうやけど、なんせコードが1行になってかっちょえーよね。

もう1つの典型的なPythonicな構文の例として、enumerate関数の使い方があります。

だって。その例文が以下。

>>> i = 0
>>> seq = ["one", "two", "three"]
>>> for element in seq:
...     seq[i] = '%d: %s' % (i, element)
...     i += 1
...
>>> seq
['0: one', '1: two', '2: three']

ふむ。ほいでー

>>> seq = ["one", "two", "three"]
>>> for i, element in enumerate(seq):
...     seq[i] = '%d: %s' % (i, element)
...
>>> seq
['0: one', '1: two', '2: three']

さらにーリスト内包表記でリファクタリング

>>> def _treatment(pos, element):
...     return '%d: %s' % (pos, element)
...
>>> seq = ["one", "two", "three"]
>>> [_treatment(i, el) for i, el in enumerate(seq)]
['0: one', '1: two', '2: three']