bhaskarc
bhaskarc

Reputation: 9531

Looping structure best approach

Consider these two variants of the same loop structure:

x = find_number_of_iterations()
for n in range(x):
    # do something in loop

and:

for n in range(find_number_of_iterations()):
    # do something

Will the second loop evaluate the method find_number_of_iterations in every subsequent loop run, or will the method find_number_of_iterations be evaluated only once even in the second variant?

Upvotes: 0

Views: 71

Answers (3)

John Coleman
John Coleman

Reputation: 52008

I suspect that your mentor's confusion is traceable to the fact that the semantics of Python's for loop is so much different than in other languages.

In a language like C a for loop is more or less syntactic sugar for a while loop:

for(i = 0; i < n; i++)
{
   //do stuff
}

is equivalent to:

i = 0;
while(i < n)
{
    //do stuff
    i++
}

In Python it is different. Its for loops are iterator-based. The iterator object is initialized just once and then consumed in subsequent iterations. The following snippets show that Python's for loop is not (easily) translatable into a while loop, and also shows that with a while loop your mentor's concern is valid:

>>> def find_number_of_iterations():
    print("called")
    return 3

>>> for i in range(find_number_of_iterations()): print(i)

called
0
1
2

>>> i = 0
>>> while i < find_number_of_iterations():
    print(i)
    i += 1


called
0
called
1
called
2
called

Upvotes: 1

jonrsharpe
jonrsharpe

Reputation: 122116

Either way, the function only gets called once. You can demonstrate this as follows:

>>> def test_func():
    """Function to count calls and return integers."""
    test_func.called += 1
    return 3

# first version
>>> test_func.called = 0
>>> x = test_func()
>>> for _ in range(x):
    print 'loop'


loop
loop
loop
>>> test_func.called
1

# second version
>>> test_func.called = 0
>>> 
>>> for _ in range(test_func()):
    print 'loop'


loop
loop
loop
>>> test_func.called
1

The function is called once, and the result of calling that function is passed to range (then the result of calling range is iterated over); the two versions are logically equivalent.

Upvotes: 1

AlG
AlG

Reputation: 15167

The function is called once. Logically, were it to be called on every iteration then the loop range could change causing all kinds of havoc. This is easily tested:

def find_iterations():
    print "find_iterations called"
    return 5

for n in range(find_iterations()):
    print n

Results in:

$ python test.py
find_iterations called
0
1
2
3
4

Upvotes: 1

Related Questions