何かを書き留める何か

数学や読んだ本について書く何かです。最近は社会人として生き残りの術を学ぶ日々です。

『Effective Python』Item 6: 単一のスライスではstart, end, strideの同時利用を避ける

『Effective Python』の続き。Item 5の続きでもある。

Effective Python: 59 Specific Ways to Write Better Python (Effective Software Development Series)

Effective Python: 59 Specific Ways to Write Better Python (Effective Software Development Series)

www.effectivepython.com

Pythonのシーケンスのスライスには切り取る間隔を指定するオプションがある。 筆者が言いたいことは、次のコードを見ればわかると思う。

a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
a[::2]
a[::-2]
a[2::2]
a[-2::-2]
a[-2:2:-2]
a[2:2:-2]

それぞれの出力がどうなるか、わかるだろうか、というのが主題である。

『Effective Python』Item 7: mapやfilterの代わりにリスト内包を使おう

『Effective Python』の続き。まさかの連投。

Effective Python: 59 Specific Ways to Write Better Python (Effective Software Development Series)

Effective Python: 59 Specific Ways to Write Better Python (Effective Software Development Series)

www.effectivepython.com

リスト内包とmap/filterはどちらが先に登場したのだろうか。PEP 202 - PEP 202 -- List Comprehensions | Python.orgを見るとリスト内包が後のように思われる。 https://hg.python.org/cpython/raw-file/v2.0.1/Misc/NEWSを見る限りPython2.0から登場したらしい。 入門書だとリスト内包は難しいから…と誤魔化しているのもあったりするが、そんなに難しくは無いと思う。

平方のリストを作りたい、という場合、

よくある方法

squares = []
for x in range(10):
    squares.append(x**2)

print(squares)

map/filterで頑張った例

squares = list(map(lambda x: x**2, range(10)))
print(squares)

リスト内包

squares = [x**2 for x in range(10)]
print(squares)

となるが、リスト内包が一番シンプルだしわかりやすい。

map(lambda x: x**2, filter(lambda x: x % 2 == 0, a))

と書いてあって一体何をしているのかすぐわかるだろうか、という話である。

『Effective Python』Item 8: リスト内包表記では2つ以上の式を避ける

『Effective Python』の続き。邦訳は出るのですか。

Effective Python: 59 Specific Ways to Write Better Python (Effective Software Development Series)

Effective Python: 59 Specific Ways to Write Better Python (Effective Software Development Series)

www.effectivepython.com

list.appendよりもリスト内包表記のほうが効率がよいという話もあり、つい無理してリスト内包表記を使ってしますが、それを戒めるかのような項目である。

my_lists = [
    [[1, 2, 3], [4, 5, 6]],
    [[7, 8, 9], [10, 11, 12]],
]
flat = [x for sublist1 in my_lists
        for sublist2 in sublist1
        for x in sublist2]
print(flat)

のような複雑なリスト内包表記はやめましょう、という話である。

なお、この項目ではリストの平滑化を題材となっているが、実際に平滑化を行う際はitertoolsを使うとよい。

from itertools import chain

def flatten(listOfLists):
    return chain.from_iterable(listOfLists)

my_lists = [
    [[1, 2, 3], [4, 5, 6]],
    [[7, 8, 9], [10, 11, 12]],
]

flat_my_list = list(flatten(flatten(my_lists)))
print(flat_my_list)

うーん、わかりやすいだろうか…。

flattenで1段階平滑化するので2回利用している。 一発で多重化のレベルに依存しない平滑化の函数はかけるだろうか。