1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Whileを使わずに無限ループさせて遊びたい!

Posted at

はじめに

 今回はいろいろな方法で無限ループさせて遊んでみました。本題に入る前に、いわゆる普通の無限ループを置いておきます。これ以降一切whileを使いません。

while True:
    print("This is an infinite loop")

このようにThis is an infinite loopを無限に表示するのが目的です。厳密には無限でないものもありますが、回数を指定せずに限界まで勝手に表示し続けるものは、仲間に入れてあげたいと思います。

itertools.cycle

import itertools
for _ in itertools.cycle([None]):
    print("This is an infinite loop")

エントリーナンバー1のitertools.cycleです。通常の使い方は、リストを渡して、その要素を順番に取り出してもらう事です。今回は取り出したものは無視して、ただ無限ループを作るのに使いました。

class MyIterator:
    def __init__(self, arr):
        self.arr = arr
        self.current = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.current >= len(self.arr):
            self.current = 0
        item = self.arr[self.current]
        self.current += 1
        return item
def my_cycle(arr):
    for i in MyIterator(arr):
        yield i
for _ in my_cycle([None]):
    print("This is an infinite loop")

自作するとこんな感じですね。

itertools.repeat

import itertools
for _ in itertools.repeat(None):
    print("This is an infinite loop")

エントリーナンバー2のitertools.repeatです。こちらは一つ渡してあげると、それを繰り返し返してくれるものです。例によって帰ってくるものは無視して、ただ無限ループを回すために使っています。

class MyIterator2:
    def __init__(self, value):
        self.value = value
    def __iter__(self):
        return self
    def __next__(self):
        return self.value
def my_repeat(value):
    for i in MyIterator2(value):
        yield i
for _ in my_repeat(None):
    print("This is an infinite loop")

自作するとこんな感じですね。

itertools.count

import itertools
for _ in itertools.count():
    print("This is an infinite loop")

エントリーナンバー3のitertools.countです。こちらは数字を渡すと、その数字からカウントアップしてくれるものです。しつこいですが、今回はループを回すためだけに使っています。

class MyIterator3:
    def __init__(self, value = None):
        self.value = 0 if value is None else value
    def __iter__(self):
        return self
    def __next__(self):
        value = self.value
        self.value += 1
        return value
def my_count():
    for i in MyIterator3():
        yield i
for _ in my_count():
    print("This is an infinite loop")

イテレーター(最小限)

class MyIterator4:
    def __iter__(self):
        return self
    def __next__(self):
        return None
for _ in MyIterator4():
    print("This is an infinite loop")

エントリーナンバー4のイテレーター(最小限)です。先ほどまでの流れで、察しの良い方は気づいたと思います。無限ループを作るだけなら、何の処理もせずNoneを返しとけばいいですし、引数もいらないですよね。

append

arr = [None]
for i in arr:
    print("This is an infinite loop")
    arr.append(i)

エントリーナンバー5のappendです。for i inarrから取り出しつつ、arrappendすることで、無限ループさせています。どんどん配列が長くなっていくので、厳密にはメモリの限界が来たら終わりますが。記事の趣旨にはあってると思うので紹介しています。

再帰呼び出し

def loop():
    print("This is an infinite loop")
    loop()
loop()

エントリーナンバー6の再帰呼び出しです。これも再帰呼び出しの深さに上限が設けられてるので、厳密には無限じゃないですね。ですが、普通にプログラムを書いていても、終了条件のミスで遭遇しますので、仲間に入れてあげました。

デストラクタ

class Loop:
    def __init__(self):
        print("This is an infinite loop")
    def __del__(self):
        Loop()
Loop()

エントリーナンバー7のデストラクタです。デストラクタっていうのは、コンストラクタの反対で、インスタンスが破棄されるときに呼び出されるやつです。デストラクタの中で、新しくインスタンスを作ることで、無限ループを実装しています。敵を一体倒すと新しい敵が出てくるみたいな時には、実用できるかもしれません。ただし、終了条件をミスるとctrl + Cでも止まらない、ガチの無限ループに陥るので危険です。

相互import

test2.py
import sys, importlib, test3
sys.setrecursionlimit(5000)
print("This is an infinite loop")
del sys.modules['test3']
import test3
importlib.reload(test3)
test3.py
import sys, importlib, test2
del sys.modules['test2']
import test2
importlib.reload(test2)

エントリーナンバー8の相互importです。こんなものは前代未聞なんじゃないでしょうか。ただお互いにimportするだけだと、2,3回しか出力されなかったので、importしてある情報を消して、なかったことにしてから再度importして、その上で再読み込みするというのをお互いにやっています。再帰呼び出しの一種っぽいので、これも厳密には無限ではなかったです。というか150回くらいしか出力されずに、上限に達してしまうので、再帰呼び出しの上限を5000回に増やす悪あがきをしています。

最後に

 ここまで読んで下さりありがとうございました。一応何か一言残すなら、イテレーターと再帰呼び出しを使うときは、終了条件に気を付けよう!といったところでしょうか。他に面白いものを見つけたら追記するかもしれません。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?