PythonTips
version | date | memo |
---|---|---|
0.1 | 2014/11/15 | first |
概要
2年ぐらいPythonをやっていて溜まってきたTipsを書く
Python Tips Index
関数型言語っぽい実装
curry化
PythonのDecorator機能を用いて、curry化を実装出来る。
下記URLに実装と使い方が載っている。
PythonDecoratorLibrary - Python Wiki
実際にプログラムに組み込む際は、上記ファイルを「curry.py」などで保存して、「from curry import curried」をimport文で記述すると良い。
メソッドチェーン的な何か
此処の記事の「f_chain」を利用してメソッドチェーン的なものを利用する。
Python で Clojure っぽい関数チェーン。 - 水底で思うこと
下記の様にすると、partialが不要になり、便利さが更に加速する。
@curried def cmap(f, x): # curry化対応map return map(f, x) f_chain(a, sorted, reversed, cmap(str), '-'.join, print)
Iteration関連のゆーてぃりてぃ
Iterableかどうか
下記URL参照
A-Liaison BLOG: Pythonで変数の型をチェックする方法(Javaでいうinstanceofが使いたい)
def isiterable(x): return isinstance(x, basestring) or hasattr(x, '__iter__')
最終要素のフラグ付きループ
Iterableなデータ(iter, string, list, dict...)を渡すと、最終要素かどうかのフラグと要素を返すiteratorを返す。
def last_flagged(x): if not isiterable(x): raise TypeError("Invalid Type, Must be iterable: %s" % type(x)) seq = iter(x) cur = next(seq) for y in seq: yield False, cur cur = y else: yield True, cur # 使い方 for flag, x in last_flagged([1,2,3]): print flag, x # => False, 1 # False, 2 # True, 3
タプルキーの分解
辞書形式でデータを登録する際に、キーをタプルで登録しておいて、後でキーの階層化を行う関数。
これを使うので注意
from collections import defaultdict def split_keys(dic): if not isinstance(dic, dict): raise TypeError("Invalid Type, Must be dict: %s" % type(dic)) result = dict() for mul_key, val in dic.items(): target = result # ループ用 for flag, key in last_flagged(mul_key): if flag: target[key] = val continue # keyを持っていない場合は初期化 if not target.has_key(key): target[key] = {} target = target[key] # 次の階層へ return result ## 使い方 dic = {} dic[(1,2,3)] = 10 dic[(1,2,4)] = 20 dic[(1,3,3)] = 30 dic[(1,3,4)] = 40 print split_keys(dic) # => {1: {2: {3: 10, 4: 20}, 3: {3: 30, 4: 40}}} # 但し # dic[(1,2)] = 10 # などタプルのサイズが違うものが混じっているとエラーになるので注意
辞書をデフォルト値で持つdefaultdict
defaultdict(dict)としようとすると、エラーになってしまうが、どうにかしてdefaultdictの初期値をdict(又はdefaultdict)にしたいという場合。
下記参照
dictionary - Multiple levels of 'collection.defaultdict' in Python - Stack Overflow
dic = defaultdict(lambda : dict) dic[1][2] = 2 # => {1: {2: 2}} dic2 = defaultdict(lambda : defaultdict(int)) dic2[1][2] += 1 # => {1: {2: 1}} # 初期値が0なので1となる