Hamzah Nasser
Hamzah Nasser

Reputation: 31

Can I make a for loop go forever? (Python)

If I have code like this:

for i in range(3):
    print("Hello")

Is there a way to make it print forever with a for loop?

Upvotes: 1

Views: 2228

Answers (3)

Grismar
Grismar

Reputation: 31319

If your for loop takes its data from a generator that runs forever, sure:

def infinite():
    while True:
        yield


for __ in infinite():
    print("Hello")

You asked if it could be done as a one-liner. Not like this, but with some trickery (and without cheating by just importing it from elsewhere like itertools):

for __ in iter(int, 1):
    print("Hello")

This works because int() will just return 0 endlessly, never reaching the sentinel value of 1. I still feel it's cheating a bit though, you'd only ever do this to make the point that it can be done with for - obviously while True: is the way to go if you seriously need this.

You asked how for __ in iter(int, 1): works exactly. The documentation for iter() is fairly clear https://docs.python.org/3/library/functions.html#iter, but the short version is that if two arguments are given, the second acts as a sentinel and the first argument has to be a callable which will be called with no arguments and until the sentinel value is returned, all values up to the sentinel will be yielded from the iterator.

For example:

from random import random


def coin_flip():
    return 'heads' if random() > .5 else 'tails'


print(list(iter(coin_flip, 'heads')))

Here, coin_flip() is a function that returns 'heads' or 'tails' at random, with an about 50/50 chance. iter(coin_flip, 'heads') creates an iteratable that will call coin_flip() and yield the result until it returns the sentinel value (which won't be yielded).

So, there's a 50% chance you get [], a 25% chance you get ['tails'], a 12.5% chance you get ['tails', 'tails'], etc.

Another way to look at it, is a mock implementation of iter():

def iter(callable, sentinel):
    while (result := callable()) != sentinel:
        yield result

This doesn't implement all of iter()s functionality though, since it works differently if you only call it with a single argument.

In the original answer, it works because int() will always return 0, which never becomes 1, so the iterator yields 0 forever.

Upvotes: 6

anarchy
anarchy

Reputation: 5184

Is there any reason it needs to be a for loop?

You could just use a while loop,

while True:
    print('hello')

To stop it press Ctrl + c on your keyboard.

Upvotes: 4

Mad Physicist
Mad Physicist

Reputation: 114290

You can use something like itertools.count:

from itertools import count

for i in count():
    print(i)

Upvotes: 4

Related Questions