def index_words(text):
result = []
for index,letter in enumerate(text):
if letter == ' ':
result.append(index)
return result
def index_words_iter(text):
'''
result = list(index_words_iter(text))
'''
for index,letter in enumerate(text):
if letter == ' ':
yield index
def normalize(numbers):
# ジェネレータを弾く
if iter(numbers) is iter(numbers):
raise TypeError('Must supply a container')
total = sum(numbers)
result = []
for value in numbers:
percent = 100 * value / total
result.append(percent)
return result
class ReadVisits(object):
def __init__(self,data_path):
self.data_path = data_path
def __iter__(self):
with open(self.data_path) as f:
for line in f:
yield int(line)
visits = ReadVisits(path)
percentages = normalize(visits)
print(percentages)
18 可変長引数
同じ処理をする引数が0~nこある時は、可変長引数を用いると良い
def log(message, *values):
if not values:
print(message)
else:
values_str = ','.join(str(x) for x in values)
print(message,values_str)
def log(message,when=datetime.now()):
print(when,message)
def log(message,when=None):
when = datetime.now() if when is None else when
print(when,message)
オライリーの本。Pythonプログラムを改良する59項目が書いてある。 使えそうなのだけメモる。
9 メモリが大きな内包表記にはジェネレータ式を使う
ジェネレータはリスト内包表記と同じ構文で周囲を()で囲えば良い。 また、ジェネレータは組み合わせをすることができる。
13 try/except/else/finallyを使って例外処理する
14 関数でNoneを返さない。
Pythonにおける評価式ではNoneの他に0や空文字もFalseになってしまうので、 関数はNoneを返すより、raiseで例外を返した方が良い
16 ジェネレータによるコード整備
空白文字の位置を返す関数を考える。 こういう時はindexを集めたリストを返すより、そのままジェネレーターでindexを返した方がわかりやすい しかも、メモリクラッシュを防げる
18 イテラブルなコンテナの定義
ジェネレータは呼び出しに対して初回しか値を返さない。 しかもエラーを吐かないので、意図しない挙動をすることがある。
複数回呼び出したいかつ、メモリクラッシュを防ぎたい時は
例えば、txt内の文章(数値)を全てreadし、100%に正規化したい場合は以下のようにすると良い。
18 可変長引数
同じ処理をする引数が0~nこある時は、可変長引数を用いると良い
ただし、新たな位置引数の追加などは難しいので要注意
20 動的なデフォルト値をキーワード引数に与える
関数のデフォルト値はimport 時の一回しか参照しない。 したがって、動的な引数を取りたい時はNoneを一度与え、関数内で定義する。 この時しっかりドキュストリングを書いた方が良い。
21 キーワード専用引数
キーワード引数を、デフォルト値または、関数定義時に絶対指定させるといった用法で使いたい時。 つまり、位置引数で書き換えて欲しくない時に使う。
例えばbool値など、どっちがどっちの引数を表しているか間違えやすい時などに有効。 *を加えて、キーワード専用引数の開始を指定する。
22 辞書の要素が辞書になる時などはヘルパークラスを使おう
ex)ある生徒がある科目のテストを複数回受講する。各テストには点数と重みが与えらえている。 任意の生徒に対してそれぞれ受けたテスト、ある科目の全テストの重み付き平均などを求められるようにしたい。
23 単純なインターフェースにはクラスの代わりに関数を使う。
Pythonには、関数を引き渡すことによって振る舞いをカスタマイズできる組み込みAPIが多くある。 (フックと呼ぶ) ex)list型のsort,defalutdictの引数など こういう時に、クラスのように内部状態を保持させたい&関数のように呼び出しを簡単にしたい状況が起こり得る。 そういう時はクラスにcallメソッドを実装すると、良い。 これはオブジェクトが関数のように呼び出されるのを許す。
24 @classmethodを使い、オブジェクトをジェネリックに構築
参考: https://blog.pyq.jp/entry/Python_kaiketsu_190205
下記のように、関数内部で特定のクラスを呼ぶ時、普通に実装してしまうと 全くジェネリックで無くなってしまう。InputDataのサブクラスで別のものを使いたい時に 書き換える必要があるからだ。 サブクラスを引数にとるという方法もあるが、この場合全てのサブクラスのinitを共通のものにするという制約がついてしまう。この時、@classmethodを使うと良い。 こうすると、クラスをオブジェクト化する必要がなく特定のメソッドが使えるようになる。 (つまりinitを省くことができる?) よく、そのクラス自身を作る時に使われる。
To be continued...