とある記事を見て面白そうだったのでやってみました。
例外の遷移での特殊な所は、処理の継続?部分をスキップできるところ
個人的には例外での遷移の特殊な所は、処理の継続?の部分を捨ててexceptした所にjumpすることだと思います。
具体的には、以下の様な感じです。
try:
print(object() + 1)
except TypeError:
print("hai")
# hai
通常の処理ならば object() + 1
に対する継続?である print()
呼び出しをスキップすることはできないですが。エラーが発生したら例外が投げられる。例外を処理する部分(try-except)が存在したら、そこで投げられた例外をキャッチする。という仕組み担っているため、 print()
呼び出しをスキップすることができています。
例外発生が終了条件としてみても
また、iterable objectのStopIterationではないですが、例外が発生したら止まる。そういう仕様にすることでループの終了条件にすることもできそうです。
幸い、通常のfizzbuzzは「1~100」までとなっています。また100を文字列にしてその長さを取ると len("100")
は3なので、3桁目の最初で例外を投げれば良いということになります。これには長さが3のリスト(xs)を作ってそれに対して xs[len(str(i))]
とでもやってあげれば大丈夫そうです。
そんなわけで
何か制約を付けて書いてみた方が良い気もしましたが特に良い物を思いつきませんでした。無駄にループではなく再帰してたりしてます。
import sys
xs = ["fizz", "", ""]
def g(i, x, out):
try:
return out((i % 5) or "buzz")
except TypeError:
try:
x = xs[i % 3] or (i % 5) / (i % 5) and i
return out(i, int(x), out)
except ValueError:
try:
x += g(i, x, lambda y: y)
except TypeError:
pass
except ZeroDivisionError:
x = "buzz"
out(i, x, out)
try:
g(1, None, lambda i, x, out: xs[len(str(i))][g(i + 1, sys.stdout.write("{}\n".format(x)), out)])
except IndexError:
pass
あとは例外処理のエラーメッセージからfizzbuzzを作っても良さそうですが止めました。