Search code examples
pythonloopsfor-loopvariablesincrement

How a for in loop in python ends when there is no update statement in it?


For example:

#1
val = 5
for i in range(val) :
    print(i)

When the range is exhausted i.e. last value reached how python knows for in loop ends . As in other languages

#2
for(i=0;i<=5;i++){
    print(i)
}

As in this exp. when i's values becomes larger than 5 false condition leads to termination of loop .

I tried reading docs of python and browsed over google but no satisfying answer. So unable to get a picture of this .


Solution

  • So this is actually a complicated question, but the very rough version of the answer is "the compiler/interpreter can do what it wants".

    It isn't actually running the human-readable text you write at all - instead it goes through a whole pipeline of transformations. At minimum, a lexer converts the text to a sequence of symbols, and then a parser turns that into a tree of language constructs; that may then be compiled into machine code or interpreted by a virtual machine.

    So, the python interpreter creates a structure that handles the underlying logic. Depending on the optimizations performed (those are really a black box, it's hard to say what they do), this may be producing structures logically equivalent to what a Java-like for loop would make, or it could actually create a data structure of numbers (that's what the range() function does on its own) and then iterate over them.

    Editing to give some more foundation for what this construct even means:

    Python iteration-style loops are different in how they're defined from C-style i++ sorts of loops. Python loops are intended to iterate on each element of a list or other sequence data structure - you can say, for instance, for name in listOfNames, and then use name in the following block.

    When you say for i in range(x), this is the pythonic way of doing something like the C-style loop. Think of it as the reverse of

    for(int i = 0; i < arr.length(); i++){
        foo(arr[i[)
    }
    

    In that code block you're accessing each element of an indexible sequence arr by going through each valid index. You don't actually care about i - it's just a means to an end, a way to make sure you visit each element.

    Python assumes that's what you're trying to do: the python variant is

    for elem in arr:
       foo(elem)
    

    Which most people would agree is simpler, clearer and more elegant.

    However, there are times when you actually do want to explicitly go number by number. To do that with a python style, you create a list of all the numbers you'll want to visit - that's what the range function does. You'll mostly see it as part of a loop statement, but it can exist independently - you can say x = range(10), and x will hold a list that consists of the numbers 0-9 inclusive.

    So, where before you were incrementing a number to visit each item of a list, now you're taking a list of numbers to get incrementing values.

    "How it does this" is still explanation I gave above - the parser and interpreter know how to create the nitty-gritty logic that actually creates this sequence and step through it, or possibly transform it into some logically equivalent steps.