Python 3.10.11 を使って実験しました。
pythonにおいて、tuple
, max
, min
, sum
などは、iterableを引数にできるため、
tuple(range(10))
max(range(10))
min(range(10))
sum(range(10))
のように書くことが可能だ。一方で、書き方としてtuple(list(range(10)))
のように一旦listに変換してからtuple
やmax
を使っても文法上は問題ない。しかし、listへの変換が挟まるのだから微差とは言え遅くなるだろうと直観的には考えられる。
%%timeit
max(range(10000))
205 µs ± 8.12 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%%timeit
max(list(range(10000)))
221 µs ± 11.7 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
これは直観通り。が、次のように書くと予想は裏切られる。
%%timeit
max(i for i in range(10000))
379 µs ± 30.9 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%%timeit
max([i for i in range(10000)])
247 µs ± 23 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
いやいや、そんな書き方しないよ、と思うかもしれないが、こういうことはよくやる。
t = [(i, i + 1) for i in range(10000)]
%%timeit
max(i[0] for i in t)
591 µs ± 7.83 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%%timeit
max([i[0] for i in t])
514 µs ± 23.4 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
やはり、一度listにした方が速い。
理由は不明。この計測方法だとキャッシュしてしまうのかと思ったが違うようだ。listはiteratorより優遇されているのかもしれないが、この結果はモヤる……