In Python I can implement a loop with step counter and a stop condition as a classical case of for loop :
for i in range(50):
result = fun(i)
print(i, result)
if result == 0:
break
where fun(x)
is some arbitrary function from integers to integers.
I always in doubts if that is the best way to code it (Pythonically, and in terms of readability and efficiency) or is it better to run it as a while loop:
i = 0
result = 1
while result != 0 and i < 50:
result = fun(i)
print(i, result)
i += 1
which approach is better? In particular - I'm concerned about the usage of break
statement which doesn't feel right.
The for
loop is slightly more performant than the while
because range()
is implemented in C, meanwhile the +=
operation is interpreted and requires more operations and object creation/ destruction. You can illustrate the performance difference using the timeit
module, for example:
from timeit import timeit
def for_func():
for i in range(10000):
result = int(i)
if result == -1:
break
def while_func():
i = 0
result = 1
while result != -1 and i < 10000:
result = int(i)
i += 1
print(timeit(lambda: for_func(), number = 1000))
# 1.03937101364
print(timeit(lambda: while_func(), number = 1000))
# 1.21670079231
The for
loop is arguably more Pythonic in the vast majority of cases when you wish to iterate over an iterable object. Furthermore, to quote the Python wiki: "As the for loop in Python is so powerful, while is rarely used except in cases where a user's input is required". There is nothing un-Pythonic about using a break
statement per se.
Readability is mostly subjective, I would say the for
loop is more readable too, but it probably depends on your previous programming background and experience.
If efficiency is what you are looking for then use generator functions
In [1]: def get_result():
...: for i in xrange(50):
...: result = fun(i)
...: yield result, i
...: if result == 0:
...: break
...:
In [2]: generator_func = get_result()
In [3]: for result, i in generator_func:
...: print result, i
...:
The result of %timeit in ipython
The slowest run took 6.15 times longer than the fastest. This could mean that an intermediate result is being cached. 10000 loops, best of 3: 30.9 µs per loop
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With