実行時に解釈され、順に実行される
実行時に型が決定される言語
💡型アノテーションは単なる注釈で機能的な意味は薄い
PythonはGCを備えており、メモリ制御を明示的に行う必要がない。
1. いつ確保されて、いつ解放するか理解して利用する必要がある
2. delしたり、関数スコープから出るときにオーバーヘッドがあることを意識する
3. 知らないと見えないところで遅くなる
💡GC呼び出しを手動でやるときは何かおかしいので思いとどまる
💡リファクタリング時にずれることがあるので特に注意が必要
💡新しいものは全部Python3.xで始める
研究/学術目的で使いやすかった
💡機械学習が後押しし、研究から実用に転じた印象
Python2はHaskellを参考にしたにも関わらず、関数型のパラダイムをいち早く取り込んだだけで終わった
for文より、リスト内包表記
res = []
for item in items:
res.append({
'piyo': item
})
res = [{'piyo': item} for item in items]
💡set, dictなどジェネレータを呼び出すものも同様
💡list()ではなく、内包表記を推奨
繰り返しの参照は変数に代入
for item in items:
self.validation(item)
validation = self.validation
for item in items:
validation(item)
💡参照、関数呼び出しのオーバーヘッドはかなり重い
💡やり過ぎると可読性を下げる
定数定義はループの外に
for item in items:
init_val = {
'name': ini.get('section', 'name')
}
name = ini.get('section', 'name')
for item in items:
init_val = {
'name': name
}
💡最適化されずに毎回同じ計算が走ることを回避
インスタンス作成はループの外に
event = { ... }
for item in items:
data = Data(event)
data.select(item)
...
event = { ... }
data = Data(event)
for item in items:
data.select(item)
...
💡オブジェクトの生成コストは相応に大きいため、スコープに閉じて再生成させない
raiseとraise eは別物
try:
ret = sugoi_kinou()
except Exception as e:
raise e
try:
ret = sugoi_kinou()
except Exception:
raise
💡raise eは後続に渡すexception内容を自身以降に限定する
意図もなくマングリングしない
def __process():
yeah = party(people)
def _process():
yeah = party(people)
💡アンダースコア一つはプライベートに使う関数/変数の意味
参照渡しと値渡しはある
def func(args):
...
n = 22
func(n) # 値渡し
l = [0, 1, 2]
func(l) # 参照渡し
💡プリミティブ型は値渡し、リストや辞書は参照渡し
DataFrameの要素をループしない
for index, row in df.iterrows():
row['sum'] = row['val1'] + row['val2']
df['sum'] = df['val1'] + df['val2']
💡pandasに限らず、関数型パラダイムを持つ手続き型言語でよく見られる
💡iterrows/ilocを使う場合は、本当にDataFrameである必要があるか考える
同様にSeriesをループしていることがある
💡tolist()するなら最初からリストでやった方がよい場合もある
💡DataFrameとListの行き来もオーバーヘッドが大きい
filterするなら先にやる
df.apply(func).filter(cond)
df.filter(cond).apply(func)
💡pandasに限らず手続き型では無駄な処理が減るので、処理したいデータに先に絞る
バックスラッシュで改行、括弧内で改行
res = df.filter() \
.apply()
res = (df.filter()
.apply())
💡もちろん、好みもある
💡Pythonでは、PEP8を読むことが大事
Pythonの善し悪しを理解して使おう
💡よいPythonライフを!