はじめに
皆さんは,while
を使うべきコードをあえてfor
で書きたくなったことはありますか? (私はありません。)
今回は,そんな素直じゃない皆さんのためにwhile
をfor
で代用する方法を紹介します。
逆は簡単
今回やる逆の「for
をwhile
で代用する」はかなり簡単に実現できます。
for
が実際にどういう処理なのかを知っておくとwhile
を実装する際に理解しやすくなりため一応紹介しておきます。
Pythonのfor
はひたすらイテレータをnext
で叩いてStopIteration
例外が飛んで来たら止めるだけです。
てなわけで
i = iter(range(10))
while True:
try:
item = next(i)
print(item)
except StopIteration:
break
のようにすればOKです。
この辺りの事情を知りたい方はCpythonのソースでも眺めてみるといいかもしれません。
カスタムイテレータ
ループ回数がわからないwhile
をfor
で実現するのは難しそうなので,カスタムイテレータを定義します。
カスタムイテレータは__next__
と__iter__
を持つクラスで,この2つのメソッドがあることでfor
に食わせることができます。
__next__
は上で紹介したnext
のよって呼ばれるメソッドです。
この中で条件式を評価してあげればよいでしょう。
これを実装してあげると
class WhileIter():
def __init__(self, cond):
self.cond = cond
def __next__(self):
if self.cond():
return None
raise StopIteration
def __iter__(self):
return self
のようになります。
これを使う時は
n = 0
for _ in WhileIter(lambda: n < 10):
print(n)
n += 1
のようにします。
条件式cond
は引数を取らずbool
として評価可能な値を返す関数ですが,条件式ごときに関数を定義する必要もないので無名関数としています。
メリット・デメリット
この方法を採用することには,以下のようなメリットとデメリットがあります。
メリット
特になし。
デメリット
- 可読性が悪い。何がしたいのかわからない。何か特別な意図があるのかと考えてしまう。
- 条件評価→ジャンプだけの
while
に対して余計な処理が増えるのでパフォーマンスが低下する可能性がある。 - 頭がおかしいのではないかと同僚に勘違いされる。
etc...