タプルをreverseする
はじめに
先日、とある超レガシーなHTML(tableレイアウト)で書かれたサイトをスクレイピングしないと行けなくなったときに、取得したtd要素のうち、3の倍数番目だけが必要、なんて事がありました。
以前、初めてのPythonか何かを読んでスライスには3番目のパラメータがあるというのを思い出しました。なのでこのような場合だと[::3]としてやれば求めてるリストが得られるというわけですね。そんな感じで無事解決したのでした。
で、先日id:atsuoishimotoさんのツイートにこんなのがありました。
@atsuoishimoto: @methane w。「Pythonに慣れてるプログラマ」の定義なら、私は「スライス演算が完璧」をあげるかなぁ。さらっと[-10::-1]とか使いこなしてるのみると「お、使い込んでるな」と思う。
2011-03-02 00:45:34 via web to @methane
負の数値を指定するとシーケンスを降順に読み込んでくれるというのは気づきませんでした。
以前はあるタプルを降順にしたタプルを用意したい、といった場合に一度リストに変換してreverse()して再度タプルに変換する、なんてめんどくさいことしてましたが、これを使えば超ラクチンですね。後ろからn個飛ばしで、なんてこともできるし。
reverseと[::-1]どっちが速い?
reverseと[::-1]ではどちらが速いか気になったので調べてみました。
import cProfile def list_re(ls): ls.reverse() def list_sl(ls): result = ls[-1::-1] return result def tpl_re(tpl): l = list(tpl) l.reverse() result = tuple(l) return result def tpl_sl(tpl): result = tpl[-1::-1] return result l1 = [i for i in range(1000000)] #リストを用意する l2 = l1[:] #コピーを用意 tpl = tuple(l1) #タプルも用意 if __name__ == '__main__': cProfile.run("list_re(l1)") cProfile.run("list_sl(l2)") cProfile.run("tpl_re(tpl)") cProfile.run("tpl_sl(tpl)")
さっそく測ってみた
>>> 4 function calls in 0.005 CPU seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 0.005 0.005 <string>:1(<module>) 1 0.000 0.000 0.005 0.005 test.py:5(list_re) 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 1 0.005 0.005 0.005 0.005 {method 'reverse' of 'list' objects} 3 function calls in 0.046 CPU seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.023 0.023 0.046 0.046 <string>:1(<module>) 1 0.023 0.023 0.023 0.023 test.py:8(list_sl) 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 4 function calls in 0.078 CPU seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.035 0.035 0.078 0.078 <string>:1(<module>) 1 0.040 0.040 0.043 0.043 test.py:12(tpl_re) 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 1 0.003 0.003 0.003 0.003 {method 'reverse' of 'list' objects} 3 function calls in 0.038 CPU seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.017 0.017 0.038 0.038 <string>:1(<module>) 1 0.021 0.021 0.021 0.021 test.py:18(tpl_sl) 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
リストはreverse使ったほうが圧倒的に速いですね。reverseは元のリストそのものを操作するからかな?リストはおそらくメソッドを使って処理したほうが効率がいいだろうと思われます。
それに対し、タプルの方はスライスを使って操作したほうが良さそうですね。まあ予想通りな感じですが。