いつでも独自のdo_all
関数を作成できます。
def do_all(iterable, func):
for i in iter(iterable):
func(i)
その後、いつでも呼び出すことができます。
for
明示的なループを使用しても、実際にはパフォーマンスの問題はありません。
リスト内包表記 または を使用するとパフォーマンスの問題が発生しますが、これmap
は結果のリストを作成する場合に限られます。明らかに、途中で 5 億個のリストを作成する必要がある場合、5 億個以上のアイテムを繰り返すのは非常に遅くなります。
スプライトのリストの描画などでは、これがほぼ確実に発生しないことをここで指摘しておく価値があります。描画する 500M のスプライトがありません。その場合、None の 5 億個のコピーのリストを作成するよりも、おそらくはるかに長い時間がかかるでしょう。そして、500M のオブジェクトに対して同じ非常に単純なことを行う必要があるもっともらしいケースでは、 に切り替えるなどのより良い解決策がありますnumpy
。しかし、これが発生する可能性があるいくつかの考えられるケースがあります。
これを回避する簡単な方法は、ジェネレーター式 or itertools.imap
(または、Python 3 では単にmap
) を使用し、関数を記述して値を破棄するdispose
ことです。1 つの可能性:
def dispose(iterator):
for i in iterator:
pass
それで:
dispose(itertools.imap(Sprite.draw, sprite_list))
次のように定義することもできますdo_all
。
def do_all(iterable, func):
dispose(itertools.imap(func, iterable))
明確さや単純さのためにこれを行っている場合、それは見当違いだと思います。for ループのバージョンは完全に読みやすく、このバージョンは、間違った関数名と構文で Haskell を記述しようとしているように見えます。
もしあなたがパフォーマンスのためにそれをやっているのなら…まあ、これが問題となる実際のパフォーマンス状況があったとしたら (それはあまりありそうにないようです)、おそらく、さまざまな潜在的な の実装で遊んでみたくなるでしょうdispose
。余分な関数呼び出しを避けるために、おそらく を にdispose
戻しdo_all
、C ですべてを実装することもできます (stdlib の itertools.c から高速反復コードを借用します)。
または、より良いのはpip install more-itertools
、 を使用することmore_itertools.consume
です。価値のあることとしては、現在のバージョンはcollections.deque(iterator, maxlen=0)
. C. しかし、誰かが実装した場合、または将来の Python (または PyPy) がそれを実装するためのより高速な方法を提供する場合、more-itertools
それを見つけてコードを変更する前に追加される可能性があります。