Looping from 1 to infinity in Python - python

In C, I would do this:
int i;
for (i = 0;; i++)
if (thereIsAReasonToBreak(i))
break;
How can I achieve something similar in Python?

Using itertools.count:
import itertools
for i in itertools.count(start=1):
if there_is_a_reason_to_break(i):
break
In Python 2, range() and xrange() were limited to sys.maxsize. In Python 3 range() can go much higher, though not to infinity:
import sys
for i in range(sys.maxsize**10): # you could go even higher if you really want
if there_is_a_reason_to_break(i):
break
So it's probably best to use count().

def to_infinity():
index = 0
while True:
yield index
index += 1
for i in to_infinity():
if i > 10:
break

Simplest and best:
i = 0
while not there_is_reason_to_break(i):
# some code here
i += 1
It may be tempting to choose the closest analogy to the C code possible in Python:
from itertools import count
for i in count():
if thereIsAReasonToBreak(i):
break
But beware, modifying i will not affect the flow of the loop as it would in C. Therefore, using a while loop is actually a more appropriate choice for porting that C code to Python.

Reiterating thg435's comment:
from itertools import takewhile, count
def thereIsAReasonToContinue(i):
return not thereIsAReasonToBreak(i)
for i in takewhile(thereIsAReasonToContinue, count()):
pass # or something else
Or perhaps more concisely:
from itertools import takewhile, count
for i in takewhile(lambda x : not thereIsAReasonToBreak(x), count()):
pass # or something else
takewhile imitates a "well-behaved" C for loop: you have a continuation condition, but you have a generator instead of an arbitrary expression. There are things you can do in a C for loop that are "badly behaved", such as modifying i in the loop body. It's possible to imitate those too using takewhile, if the generator is a closure over some local variable i that you then mess with. In a way, defining that closure makes it especially obvious that you're doing something potentially confusing with your control structure.

If you want to use a for loop, it's possible to combine built-in functions iter (see also this answer) and enumerate for an infinite for loop which has a counter. We're using iter to create an infinite iterator and enumerate provides the counting loop variable. The start value is zero by default, but you can set a different start value with the start argument.
for i, _ in enumerate(iter(bool, True), start=1):
input(i)
Which prints:
1
2
3
4
5
...

If you're doing that in C, then your judgement there is as cloudy as it would be in Python :-)
For a loop that exits on a simple condition check at the start of each iteration, it's more usual (and clearer, in my opinion) to just do that in the looping construct itself. In other words, something like (if you need i after loop end):
int i = 0;
while (! thereIsAReasonToBreak(i)) {
// do something
i++;
}
or (if i can be scoped to just the loop):
for (int i = 0; ! thereIsAReasonToBreak(i); ++i) {
// do something
}
That would translate to the Python equivalent:
i = 0
while not there_is_a_reason_to_break(i):
# do something
i += 1
Only if you need to exit in the middle of the loop somewhere (or if your condition is complex enough that it would render your looping statement far less readable) would you need to worry about breaking.
When your potential exit is a simple one at the start of the loop (as it appears to be here), it's usually better to encode the exit into the loop itself.

def infinity():
i=0
while True:
i+=1
yield i
for i in infinity():
if there_is_a_reason_to_break(i):
break

def natural_numbers():
yield from map(sum, enumerate(iter(int,1)))
for i in natural_numbers():
if there_is_a_reason_to_break(i):
break;

Related

Is there a way to do conditionals inside Python (3) for loops?

Coming from primarily coding in Java and wanted to know if Python could use conditionals and different kinds of incrementing inside its for loops like Java and C can. Sorry if this seems like a simple question.
i.e.:
boolean flag = True
for(int i = 1; i < 20 && flag; i *= 2) {
//Code in here
}
Not directly. A for loop iterates over a pre-generated sequence, rather than generating the sequence itself. The naive translation would probably look something like
flag = True
i = 1
while i < 20:
if not flag:
break
...
if some_condition:
flag = False
i *= 2
However, your code probably could execute the break statement wherever you set flag to False, so you could probably get rid of the flag altogether.
i = 1
while i < 20:
...
if some_condition:
break
i *= 2
Finally, you can define your own generator to iterate over
def powers_of_two():
i = 1
while True:
yield i
i *= 2
for i in powers_of_two():
...
if some_condition:
break
The for loops in Python are not like loops in C. They are like the for-each loops applied to iterables that came out in Java 7:
for (String name: TreeSet<String>(nameList) ) {
//Your code here
}
If you want control over your iterator variable, then a while or for loop with a break in it is probably the cleanest way to achieve that kind of control.
This might be a good time to look into finding time to do a tutorial on Python comprehensions. Even though they are not directly applicable to your question, that is the feature that I appreciate most having come from Java about five years ago.
You can use range() if you have the step as some constant increment (like i++,i+=10,etc). The syntax is -
range(start,stop,step)
range(start, stop, step) is used as a replacement for for (int i = start; i < stop; i += step). It doesn't work with multiplication, but you can still use it (with break) if you have something like i < stop && condition.
The equivalent loop for the one you mentioned in question can be =>
for(int i=0;i<20;i*=2) // C/C++ loop
# Python - 1
i = 0
while i < 20 : # Equivalent python loop
# Code here
i*=2
If you are willing to use flag as well as a condition, you will have to do it as =>
// C/C++
bool flag = true;
for(int i=0;i<20&&flag;i*=2) // C/C++ loop
# Python - 1
i,flag = 1,True
while not flag and i < 20 : # Equivalent python loop
# Code here
i*=2
Hope this helps !
In a sense, but it's not quite as simple as it is with JS and Java.
Here is your example written in Python using a while loop with two conditions. Also note that in Python while loops, you cannot assign or increment the index in the loop's declaration.
boolean_flag = True
i = 1
while (i < 20 and boolean_flag):
i *= 2
# Code in here
The answers above are good and efficient for what you ask, but I'll give my idea of how I would do it.
max = 20
for i in range(0, max/2):
c = i * 2
if flag:
#Do work.
break
or to make it shorter:
max = 20
for i in range(0, max, 2):
if flag:
#Do work.
break
Firstly, in python you cannot increment using the increment operator as in C++, or Java, e.x, x++ or --x. A for loop in Python works over an iterator (For example, List, String, etc.)
PYTHON FOR LOOPS:
A for loop is used for iterating over a sequence (that is either a list, a tuple, a dictionary, a set, or a string`).
This is less like the for keyword in other programming languages, and works more like an iterator method as found in other object-orientated programming languages.
With the for loop we can execute a set of statements, once for each item in a list, tuple, set etc.
Example
Print each fruit in a fruit list:
fruits = ["apple", "banana", "cherry"]
for x in fruits:
print(x)
will print:
apple
banana
cherry
Example
Do not print banana:
fruits = ["apple", "banana", "cherry"]
for x in fruits:
if x == "banana":
continue
print(x)
PYTHON CONDITIONALS:
In python the keyword for false values is False, and that for true values is True
Like C++ or Java, you can use == to compare values. But unlike Java, where there is strict type-checking and the condition needs to be a Boolean Statement, in Python:
Almost any value is evaluated to True if it has some sort of content.
Any string is True, except empty strings.
Any number is True, except 0.
Any list, tuple, set, and dictionary are True`, except empty ones.
In fact, there are not many values that evaluates to False, except empty values, such as (), [], {}, "", the number 0, and the value None. And of course the value False evaluates to False.
The following will return False:
bool(False)
bool(None)
bool(0)
bool("")
bool(())
bool([])
bool({})
One more value, or object in this case, evaluates to False, and that is if you have an object that is made from a class with a __len__ function that returns 0orFalse`:
class myclass():
def __len__(self):
return 0
myobj = myclass()
print(bool(myobj))
You use while for flag and condition and increment inside loop
i = 1
while flag and i < 20:
# code here
i = i*2
Sure, but you may need to do some things yourself.
Python provides the range() class which produces an interable sequence of values with an optional step increment.
for i in range(1, 20, 2):
# do the things
# here, i starts at 1, and increments by 2 each loop stops at >= 20
If you want to do something more complicated like i *= 2, You have two options:
use a while loop and increment the values yourself
write a custom generator like range() that implements such a thing.
Example generator:
def range_step_mult(start, stop, step):
while start < stop:
yield start
start *= step
for i in range_step_mult(1, 100, 2):
print(i)
Note the use of the yield keyword here. This is VERY important for performance over large ranges, especially if the iterable object is on the larger side. Using the keyword here allows Python to simply deal with one object at a time as opposed to generating all that stuff in memory before it even starts working on it.
You can use conditionals within the for loop, and you can use the break and continue keywords to control the loop flow to some level. That being said, the loop is generated outside of this block, so you can't change the step or something mid loop.
While loops are a different story entirely and you can alter the step as much as you want as you're the one incrementing it in the first place.
Example while loop:
i = 1
while i < 100
if i % 2 == 0:
i *= 2
else:
i += 1
In common with several other answers, here is how I would actually translate that code:
boolean_flag = True
i = 1 # actually I wouldn't use i as a variable name, but whatever.
while i < 20 and boolean_flag:
# code goes here
i *= 2
I would also consider using a for loop, which might look something like this:
from itertools import takewhile, count
boolean_flag = True
for i in takewhile(lambda i: i < 20, map(lambda x: 2**x, count())):
# code goes here
if not boolean_flag:
break
But having considered both, I prefer the while loop. And in practice I very rarely actually need a flag defined across a loop like that. Normally you can either break from the loop immediately you detect the condition that would cause you to set the flag, or else use logic like this:
boolean_flag = something()
something_that_has_to_happen_after_regardless_of_flag_value()
if not boolean_flag:
break
The need for boolean "break" flags is mostly (not wholly) a result of trying to write all your loops with no break in them, but there's no particular benefit to doing that.
It might be possible to salvage the for loop, or at least learn a few things about Python, by playing around with other ways to write what comes after for. Like lambda i: i < 20 could be (20).__gt__, but that's breathtakingly ugly in its own way. Or map(lambda is always a warning sign, and in this case map(lambda x: 2**x, count()) could be replaced with (2**x for x in count()). Or you can use functools.reduce to change the exponentiation back to multiplication, but it's unlikely to be worth it. Or you can write a generator function, but that's a chunk more boilerplate.
Supposing I know that the base-2 logarithm of 20 can only be so big, but I don't want to make myself a hostage to stupid off-by-one errors, I could write something like:
for i in (2**x for x in range(10)):
if not i < 20:
break
Or to get rid of all of the "clever" stuff:
for x in range(10):
i = 2 ** x
if not (i < 20 and boolean_flag):
break
But again, this isn't really solving the basic issue that for loops are intended for when you have an iterable containing the right values, and in Python you need to pull several things together to come up with the right iterable for this case (especially if you want to write 20 rather than the logarithm of 20). And that's even before you deal with the flag. So, in general you use a for loop when you have something to iterate over, or can easily produce something to iterate over, and use a while loop for more general looping based on mutating local variables.
Frankly for those specific numbers you might as well write for i in (1, 2, 4, 8, 16) and have done with it!

skip iterations in for loop in python?

I have programmed in C++ earlier but I am new to Python. I searched for this but i was not able to find the appropriate answer. In C++, I can do:
for(int i=0; i<10;i++)
{
i+=5;
std::cout<<i<<std::endl
}
The values of i would be 5 and 11. But in python if i do:
for i in range(0,10):
i+=5
print i
The value of i does update for that iteration of loop, but in the next iteration, it will become 1.
While I do understand that in python, after each iteration, i will contain the next value in the tuple/list generated by range, but is there any way I can make it skip iterations like in C++? I really don`t want to use the next() function 5 times
EDIT: I can use the third parameter of range function for general use, but what if I want to skip some iterations for say if only a certain condition is true. eg
for(int i=0; i<10;i++)
{
if(i%2)i+=1;
std::cout<<i<<std::endl
}
If you want to skip iterations when a condition is true, then use continue:
for i in range(10):
if i % 2:
continue
print(i)
You can use a regular while loop. it will look less nice but it does the job.
for example:
i = 0
while i < 100:
print i
if i % 2 == 0:
i += 5
i+=1
I know what you were thinking, but there's something built-in for python that allows you to set the iteration step within the range() function. Here is the official Python Documentation on range().
In essence, to skip x after each iteration, you would do:
for i in range(start, stop, x + 1):
# functions and stuff
Hope this helped.

Manual stepping in python for [duplicate]

This question already has answers here:
How do I use a C-style for loop in Python?
(8 answers)
Closed 8 years ago.
In C++, I can do this:
for( int i=0; i<10; ++i ) {
if( something ) i += 3;
}
How can I do the same in Python?
for i in range(10):
# ????
Python for loops work on iterators. If you run on an iterator object that you have bound to a name, you can make the loop skip future values by calling next yourself:
it = iter(iterable) # create our own iterator
for i in it: # loop on it
# do stuff with i
if something:
next(it) # discard the next three values
next(it)
next(it)
You can of course use the return values from the next(i) calls, if you want. This can be handy for some kinds of text data files, where one header line specifies the meaning of the next few data lines.
You should be aware though that if you reach the end of the iterable sequence, next will raise a StopIteration exception. If that happens in the for loop's iteration, it takes care of the exception for you, but if it happens when you call next yourself, it will not be. If an unexpected end of the data is not an unrecoverable error, you will probably want to use a try/except block to suppress the exception.
The basic equivalent in Python is this:
for i in range(start, stop, increment):
do_something(i)
That means that the following codes behave identically:
for (int i = 10; i >= 1; i -= 2) {
doSomething(i);
}
for i in range(10, 0, -2):
do_something(i)
Normally, we want to start at zero, increment by one, and stop at a certain number, which leads to the shortcut:
for i in range(stop):
do_something(i)
If you want to modify 'i', and have it affect how many times you loop, you must use a 'while' loop:
i = 0
while i <= 10:
if (something):
i += 3
i += 1
...which is what you should also be doing in C++. A 'for' loop is for repeating a definite number of times. If you're modifying the counter inside the loop, then the loop is no longer definite and you should be using a while loop instead, since it's semantically a better fit.
i=0
while i<10:
if something:
i += 3
else:
i += 1

For (not foreach) loop in Python

I need to make a simple python script, but as I mostly do PHP / C++ I find it hard to manage myself without simple for loops.
Let's say I have a code:
for(int i = 0; i < some_string_length; i++)
{
//do something...
}
As you can see it simply goes as many times as many letters I have in my string. Of course, I could do this in a while loop, but that has an issue. I have to either create a variable outside of the loop which will make it global or create it inside the loop, but this variable's value can't be used in the argument of loop.
Wrong:
while(i < some_string_length)
{
i = something; //declaring i for the first time
i++;
}
As you can see it doesn't make sense at all. So how can I do this?
The construct from other languages
for (int i = start; i < stop; i += step) { … }
translates directly into a Python for loop over a range:
for i in range(start, stop, step):
…
By default, step is 1, so you don’t need to specify it for i++. start defaults to zero, so you can also leave that out, if you start with i = 0:
for i in range(stop): # the same as `for (int i = 0; i < stop; i++)`
…
So, if you want to iterate i over the length of a string, you can just do this:
for i in range(len(my_string)):
…
Usually, you would want to access the character of that string though, so you can just iterate over the characters directly:
for char in my_string:
…
Or, if you really do need the index as well, you can use enumerate to get both:
for i, char in enumerate(my_string):
…
for i, item in enumerate(some_string):
# i is the index, item is the actual element
I think you'd be surprised how rarely you actually need i, though. You're better off learning how to use Python idioms, rather than forcing yourself to write PHP/C++ code in Python.
Try:
for i in range(0,some_string_length):
# do something...
I think you want to use the range function
for x in range(0, 3):
print "x: %d" (x)
https://wiki.python.org/moin/ForLoop
If you have a string s:
s = "some string"
you can do this:
for i in range(len(s)):
print i

How do I skip a few iterations in a for loop

In python I usually loop through ranges simply by
for i in range(100):
#do something
but now I want to skip a few steps in the loop. More specifically, I want something like continue(10) so that it would skip the whole loop and increase the counter by 10. If I were using a for loop in C I'd just sum 10 to i, but in Python that doesn't really work.
You cannot alter the target list (i in this case) of a for loop. Use a while loop instead:
while i < 10:
i += 1
if i == 2:
i += 3
Alternatively, use an iterable and increment that:
from itertools import islice
numbers = iter(range(10))
for i in numbers:
if i == 2:
next(islice(numbers, 3, 3), None) # consume 3
By assigning the result of iter() to a local variable, we can advance the loop sequence inside the loop using standard iteration tools (next(), or here, a shortened version of the itertools consume recipe). for normally calls iter() for us when looping over a iterator.
The best way is to assign the iterator a name - it is common have an iterable as opposed to an iterator (the difference being an iterable - for example a list - starts from the beginning each time you iterate over it). In this case, just use the iter() built-in function:
numbers = iter(range(100))
Then you can advance it inside the loop using the name. The best way to do this is with the itertools consume() recipe - as it is fast (it uses itertools functions to ensure the iteration happens in low-level code, making the process of consuming the values very fast, and avoids using up memory by storing the consumed values):
from itertools import islice
import collections
def consume(iterator, n):
"Advance the iterator n-steps ahead. If n is none, consume entirely."
# Use functions that consume iterators at C speed.
if n is None:
# feed the entire iterator into a zero-length deque
collections.deque(iterator, maxlen=0)
else:
# advance to the empty slice starting at position n
next(islice(iterator, n, n), None)
By doing this, you can do something like:
numbers = iter(range(100))
for i in numbers:
...
if some_check(i):
consume(numbers, 3) # Skip 3 ahead.
Why not just set the value to skip until? Like:
skip_until = 0
for i in range(100):
if i < skip_until:
continue
if SOME_CONDITION:
skip_until = i + 10
DO_SOMETHING()
where SOME_CONDITION is whatever causes you to skip and DO_SOMETHING() is the actual loop contents?
for i in range(0, 100, 10):
print(i)
will print 0, 10, 20 ...
Something that I keep using. You can use below to get a 10% prob on running your code:
import random
for i in range(1000000):
if random.random() > 0.1:
continue:
# your code
A charmed and simplest form is like that:
>>> for i in range(5,10):
... print (i)
...
5
6
7
8
9
Where 5 was the index that started iteration.

Categories