ソフトな忘却力(119) Pythonのデコレータで、while ループよけ

Joseph Halfmoon

「サイエンティフィックPythonのための」IDE、Spyder上にてScientific Python Lecturesの実習中。Pythonであると「結果が何個かわからない」ときにwhile True: の無限ループで受け取って、ループの中でbreakすることがあるかと思います。でもまイマイチ、スマートでない?

※「 ソフトな忘却力」投稿順 Index はこちら

※Sypder IDEはWindows版 6.0.8使用です。Python処理系はPython 3.11.13です。

Scientific Python Lectures様のコースは例題だけでなく、エクササイズなども充実、それを全部順番に解いていったら必ずや立派な人になれるだろ~と思います。でも老い先短い年寄には量が多過ぎて多分死ぬまでに終わりません。適当な練習でお茶を濁してます。今回は「7.2 Decorators」の「7.2.6 A while-loop removing decorator」です。

whileの無限ループ

そういうわけでPythonであると時々書いてしまう「醜い」 while True: のループですが、胸に手を当てて思い出してみると、他の言語ではこの手のループをまず書かないで済むものがあります。本サイトで利用させていただいている言語では以下のような系統の言語において、まず使わんで済む気がします(個人の感想デス。)

    • Matlab、Scilabなど
    • R言語など
    • Lispなど

上記のどの言語もベクトル(リスト)を扱うことができ、関数戻り値もベクトル化されていることが多いからかと思います。

ま、Pythonにもリストはあり、ちょこっと「シンタックス・シュガー」を振りかければ、ああら不思議、while True: のループが隠蔽されてしまうっと。その方法をお教えいただいているのが、Lecturesの「7.2.6 A while-loop removing decorator」です。

練習用のサンプル例

文句を言うわけじゃありませんが、7.2.6 A while-loop removing decoratorで掲げられている例、イマイチ、と思いました。タイトルで while-loop removing と謳っているので、例題の中には while-loop が残ってます。まあ、本質的な問題じゃない、とはいえ残念な感じです。

そこでお惚け老人が書いた例が以下に。デコレータ関数、vectorized()についてはLecturesの例題通り、その利用部分を「シンプルにして while True:を皆無」としてみました。

import functools

def vectorized(generator_func):
    def wrapper(*args, **kwargs):
        return list(generator_func(*args, **kwargs))
    return functools.update_wrapper(wrapper, generator_func)

@vectorized
def sample_generator():
    yield "abc"
    yield "def"
    yield -1
    
def main():
    obj = sample_generator()
    print(obj)

if __name__ == '__main__':
    main()

これで、オリジナルのsample_generator()関数は、呼び出す度に1個づつ返り値を返す筈だったものが、全呼び出し結果をリスト(ベクトル)で返すようになった筈。

実行結果が以下に。

results今回も関数をラッパで「包む」のに functools ご活躍だったな。

ソフトな忘却力(118) Pythonのデコレータで、非推奨の関数に自前警告 に戻る

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です