遙かなるマチョジニア

マッチョXエンジニアを目指すブログ

【書評】入門Python3 :とりあえず読んでおくべき

スポンサードリンク

ある程度pythonを触った身からすると、読んでおいて損はない本。

入門 Python 3

入門 Python 3

  • 作者:Bill Lubanovic
  • 発売日: 2015/12/01
  • メディア: 単行本(ソフトカバー)

これが全く触ったことがな人だともしかしたら読みづらいかもしれない。 そもそもオラ本が全般的に初心者に易しくない気はする(head firstシリーズは易しい?)。

  • pythonを触ったことがある人
  • python以外の言語を触ったことがある人

上記に当てはまる場合(自分はそう)は、間違いなく優良な本だった。 というのは、やはり実践主義でコードを書いていると、変な癖がつく気がしていて、 それはpythonのポリシーと合っているかわからないし、そもそも無駄な実装をしている可能性もあり、 標準ライブラリを使えば簡単に解決できるのではないか、という不安を抱いて、 この本を読んだらその不安が的中していたからである。

例えば、setクラスはずっと重複なしリストだと思い込んでいた。 「リストから重複を除外したい」と調べたら大体setを使った解法が出てくるため、 そのために作られたクラスなのだと思い込んでしまっていた。実際は集合クラスなので集合演算ができる。 他にもcsvにあるDictReaderやDictWriterも便利だなと思った(pandas使う場面が多いけど)。

とはいえ、イディオムやデザインパターンなどの内容は書いていないため、 この本を読めばシステム開発ができるとまではいかない。 にしても、どのような道具があるのかを知ることできるし、どの場面で使えばいいのかもわかるため、 今後pythonを触るエンジニアは早めに読むことをおすすめする。

個人的付箋

集合クラス

setは集合クラス。重複なしリストかと思ってたが違った。 なので集合演算ができる。

a  = {1, 2}
b = {2, 3}

a & b
a.intersection(b)
a + b
a.union(b)

elseによるbreakチェック

whileやforは、正常終了したかどうかをチェックするオプションのelseを持っている。 ループがbreak呼び出して途中で終了しておらず、最後まで実行されたときにelse内が実行される。

for c in cs:
    print('hoge')
    break
else: # breakしていない
    print('fuga')

例外

exrcept exceptiontype as name

short_list = [1, 2, 3]
while True:
    value = input('Position [ q to quit ] ? ')
    if value = 'q':
        break
    try:
        position = int(value)
        print(short_list[position])
    except IndexError as err:
        print('Bad index:', position)
    except Exception as other:
        print('Something else broke:' other)

存在しないキーの処理

存在しないキーで辞書にアクセスする際の振る舞いについて、 get()関数を使ってデフォルト値を返すようにすれば例外を避けられる。 setdefault()関数はキーがなければさらに辞書を要素に追加することができる。

periodic_table = {'Hydrogen' : 1, 'Helium' : 2}
carbon = periodic_table.setdefault('Carbon', 12)

# carbon => 12
# periodic_table =>  {'Hydrogen' : 1, 'Helium' : 2, 'Carbon', 12}

# すでにキーがある場合は更新されない
helium = periodic_table.setdefault('Helium',  923)
# helium => 2
# periodic_table =>  {'Hydrogen' : 1, 'Helium' : 2, 'Carbon', 12}

defaultdictは辞書作成時にあらゆる新キーのためにあらかじめデフォルト値を設定する。

from collections import defaultdict
periodic_table = defaultdict(int)
periodic_table['Hydrogen'] = 1
periodic_table['Lead']

periodic_table
# defaultdict(<class 'int'>, {'Lead': 0, 'Hydrogen': 1})


特殊メソッド

比較のための特殊メソッド

メソッド 意味
__eq__( self, other ) self == other
__ne__( self, other ) self != other
__lt__( self, other ) self < other
__gt__( self, other ) self > other
__le__( self, other ) self <= other
__ge__( self, other ) self >= other

算術演算のための特殊メソッド

メソッド 意味
__add__( self, other ) self + other
__sub__( self, other ) self - other
__mul__( self, other ) self * other
__floordiv__( self, other ) self // other
__truediv__( self, other ) self / other
__mod__( self, other ) self % other
__pow__( self, other ) self ** other

その他の特殊メソッド

メソッド 意味
__str__( self, other ) str(self)
__repr__( self, other ) repr(self)
__len__( self, other ) len(self)

下記でドキュメント化されている。

https://docs.python.org/3/reference/datamodel.html#special-method-names

Guidoのアドバイス

Guido van Rossum

データ構造を作り込みすぎないようにしよう。オブジェクトよりもタプルの方がいい。ゲッター/セッター関数よりも単純なフィールドを選ぶようにしよう。組み込みデータ型はプログラマーの友達だ。数値、文字列、タプル、リスト、集合、辞書をもっと使おう。そして、コレクションライブラリ、特にデックをチェックしよう。

collections --- コンテナデータ型 — Python 3.8.3 ドキュメント

名前つきタプル

from collections import namedtuple
Duck = namedtuple( 'Duck', 'bill tail' )
duck = Duck('wide orange', 'long')
# duck => Duck(bill='wide orange', tail='long)
# duck.bill => wide orange
# duck.tail => 'long'

csv

DictReaderを使って辞書リストにすることができる。 各行のキーが、各列のヘッダーとなる。

import csv
with open('villains', 'rt') as fin:
    cin = csv.DictReader(fin, fieldname=['first', 'last'])
    villanins = [row for row in cin]

DictWriterを使って辞書リストからヘッダー付きのcsvファイルを作成することができる。

with open('dst_villains', 'wt') as fout:
    cout = csv.DictWriter(fout, ['first', 'last']
    cout.writeheader()
    cout.writerows(villains)

yaml

PyYAMLは文字列からPythonオブジェクトをロードできるが、これは危険なことだ。 load()ではなくsafe_load()を使うべき。

Ned Batchelder: War is peace

timedelta

from datetime import date, timedelta
now = date.today()
one_day = timedelta(day=1)
tomorrow = now + one_day
yesterday = now - one_day

# 17日後
now + 17 * one_day

リスト内表記はappend()を使ったリストへの要素追加より速い

result =[]
for value in range(1000):
    result.append(value)

# こちらのほうが2倍以上速い
result = [value for value in range(1000)]