まえがき
今年の春から今まで、2年ぶりにPythonを沢山書いているわけなんですが、JavaScriptのクソに頭をやられて久しぶり書くだけあって基本的なところから色々と頭から抜け落ちていたわけです。
そんで何か思い出すたびに会社のwikiを使ってメモっていたのですが、せっかくなので少々訂正をしてブログにも書きます。
知ってる人は当然知ってる、でも結構長いことPythonを書いてても知らなかったりするような小技を載っけました。
なお、メタプログラミングとかの黒魔術っぽい記事のまとめはこちら:
リストの処理
インデックスを取りながら値も欲しい
Not Good:
datas = ['a', 'b', 'c'] for i in range(len(data)): print(i) print(datas[i])
Good:
datas = ['a', 'b', 'c'] for i, data in enumerate(datas): print(i) print(data)
複数のリストを同時に処理したい
Not Good:
data_a = ['a', 'a', 'a', 'a'] data_b = ['b', 'b', 'b', 'b'] min_length = min(len(data_a), len(data_b)) for i in range(min_length): a = data_a[i] b = data_b[i]
Good:
for a, b in zip(data_a, data_b): # use a, b
NOTE:
Generatorの概念が理解できているならばitertools.izipを使いましょう。ですが、貴方がバージョン3以上のPythonを使っているならば、デフォルトでzipはGeneratorを返します。
他にも、itertoolには数多くの便利な関数が用意されているので一通り目を通しておきましょう。扱いたいリストたちの状態次第では、izip_longest(あるいはzip_longest)が役に立つでしょう。
要素をリストに追加していきたい
Not Pythoniac:
li = [] for i in range(10): li.append(i)
Pythoniac:
li = [i for i in range(10)]
条件に合った要素だけをリストに追加していきたい
same as filter()
Not Pythoniac:
li = [] for i in range(10): if i % 2 == 0: continue li.append(i)
Pythoniac:
li = [i for i in range(10) if not i % 2 == 0]
リストの要素それぞれに変化を加えていきたい
same as map()
Not Pythoniac:
li = [] for i in range(10): li.append(i * 2)
Pythoniac:
li = [i * 2 for i in range(10)]
You can use this with the filter() pattern:
li = [i * 2 for i in range(10) if i % 2 == 0]
リスト内包表記以外のシンタックスについて
Generator
(i * 2 for i in range(10) if i % 2 == 0)
Set(集合型)
{i * 2 for i in range(10) if i % 2 == 0}
Dictionary
{i: i * 2 for i in range(10) if i % 2 == 0}
辞書の処理
keyが存在するかどうかをチェックする
Bad:
some_dictionary = some_func() try: some_dictionary['foo'] except KeyError: print('no key!')
Not Efficient:
if some_dictionary.get('foo') == None print('no key!')
Good:
if 'foo' in some_dictionary: print('no key!')
NOTE:
has_key新しいPythonでは使えません。
デフォルトの値を持った辞書を作成したい
Not Efficient:
result = {}
for key, v in some_values:
if key not in result:
result[key] = []
result[key].append(v)
Efficient:
from collections import defaultdict result = defaultdict(list) for key, v in some_values: result[key].append(v)
値が存在しない場合にだけ要素を追加したい
Not Efficient:
some_dictionary = some_func() if 'foo' in some_dictionary: some_dictionary['foo'] = 'default value'
Efficient:
some_dictionary.setdefault('foo', 'default value')
要素の数え上げをしていきたい
Not Efficient:
data = ['aaa', 'bbb', 'ccc', 'aaa', 'ddd'] word_and_counts = {} for word in data: if word_and_counts.has_key(word): word_and_counts[word] += 1 else: word_and_counts[word] = 1
Efficient:
from collections import Counter data = ['aaa', 'bbb', 'ccc', 'aaa', 'ddd'] counter = Counter(data)
その中でも最も頻度の高いものを取得する
If dict:
top_n =[] count = 0 for w, c in sorted(word_and_counts.iteritems(), key=lambda x: x[1], reverse=True): if count == 3: continue result[w] = c count = count + 1
If Counter:
top_n = counter.most_common(3)
ValueObjectを作りたい
Not Efficient:
and this is not Immutable
class Rect(object): x = 0 y = 0 width = 0 height = 0 def __init__(x, y, width, height): # ellipsis rect = Rect(0, 0, 0, 0)
Efficient:
and this is immutable
from collections import namedtuple Rect = namedtuple('Rect', ('x', 'y', 'width', 'height', )) rect = Rect(0, 0, 0, 0)
所感
こうして振り返るとリスト処理関係のイディオムが多い気がしますね。
何か気がつくことや、要望があれば随時書き足していきます。
Effective Python ―Pythonプログラムを改良する59項目
- 作者: Brett Slatkin,石本敦夫,黒川利明
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/01/23
- メディア: 大型本
- この商品を含むブログ (4件) を見る
サイバーセキュリティプログラミング ―Pythonで学ぶハッカーの思考
- 作者: Justin Seitz,青木一史,新井悠,一瀬小夜,岩村誠,川古谷裕平,星澤裕二
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/10/24
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (10件) を見る