2011/2/11 追記 たくさんコメントを頂きました
@t2y def limit_characters1(s, start, maximum, end=None): return [s[f:f+maximum] for f in range(start, (end if end else len(s)), maximum)]
2011-02-10 21:26:54 via web to @t2y
見易いようにコードを引用します。
def limit_characters_by_ishimoto(s, start, maximum, end=None): return [s[f:f+maximum] for f in range(start, (end if end else len(s)), maximum)]
range() だけで開始位置の計算はできました。 range() の step は知ってはいたけど、思いつかなかったです。こういう突っ込みをもらうことで1つ応用例が学べて良かったです。
もう1つ、コメントにもあるように @cocoatomo からジェネレータ一発でやってみましたとあります。
この実装を見ていていくつか気付きました。私のコードの中で、
from math import ceil div_num = int(ceil(len(_s) / float(maximum)))
と、例えば 1.2 だったら 2 といったように切り上げしたいがためにやや煩雑なことをしていますが、
def my_ceil(n1, n2): """ >>> my_ceil(0, 1) 0 >>> my_ceil(1, 1) 1 >>> my_ceil(2, 5) 1 >>> my_ceil(5, 3) 2 >>> my_ceil(8, 3) 3 """ return ((n1 - 1) / n2) + 1
でも同じことができますね。あと、私の書いたコードはジェネレータを for 文でぐるぐるまわしてますが、組み込み関数の list() にジェネレータを渡すとリストを返してくれることにも気付きました。他の人の実装を読むのは勉強になります。
def generator(num): """ >>> list(generator(5)) [0, 1, 2, 3, 4] """ return (i for i in xrange(num))
同じ環境でプロファイルを取ってみました。
In [3]: timeit -n 3 limit_characters_by_ishimoto(s, 0, 80) 3 loops, best of 3: 21.1 us per loop In [4]: timeit -n 3 list(limit_characters_by_cocoatomo(s, 0, 80)) 3 loops, best of 3: 77.3 us per loop
@atsuoishimoto の実装はループ処理がさらに効率化されて2倍速くなっていますね。
結論をまとめます。
最後に言いたいことは textwrap は覚えとこう - methaneのブログ です。
追記、終わり。
以下、簡単なテストコードです。興味のある方はどうぞ。
def test_limit_characters_null(): test_line = "" assert [] == limit_characters1(test_line, 0, 2) assert [""] == limit_characters2(test_line, 0, 2) assert [""] == limit_characters3(test_line, 0, 2) def test_limit_characters_max(): test_line = "12345" result = { 1: ["1", "2", "3", "4", "5"], 2: ["12", "34", "5"], 3: ["123", "45"], 4: ["1234", "5"], 5: ["12345"], 6: ["12345"], } for i in xrange(1, 6): r = result[i] assert r == limit_characters1(test_line, 0, i) assert r == limit_characters2(test_line, 0, i) assert r == limit_characters3(test_line, 0, i) def main(): test_limit_characters_null() test_limit_characters_max() if __name__ == "__main__": main()