How does the Python's range function work?

130,122

Solution 1

A "for loop" in most, if not all, programming languages is a mechanism to run a piece of code more than once.

This code:

for i in range(5):
    print i

can be thought of working like this:

i = 0
print i
i = 1
print i
i = 2
print i
i = 3
print i
i = 4
print i

So you see, what happens is not that i gets the value 0, 1, 2, 3, 4 at the same time, but rather sequentially.

I assume that when you say "call a, it gives only 5", you mean like this:

for i in range(5):
    a=i+1
print a

this will print the last value that a was given. Every time the loop iterates, the statement a=i+1 will overwrite the last value a had with the new value.

Code basically runs sequentially, from top to bottom, and a for loop is a way to make the code go back and something again, with a different value for one of the variables.

I hope this answered your question.

Solution 2

When I'm teaching someone programming (just about any language) I introduce for loops with terminology similar to this code example:

for eachItem in someList:
    doSomething(eachItem)

... which, conveniently enough, is syntactically valid Python code.

The Python range() function simply returns or generates a list of integers from some lower bound (zero, by default) up to (but not including) some upper bound, possibly in increments (steps) of some other number (one, by default).

So range(5) returns (or possibly generates) a sequence: 0, 1, 2, 3, 4 (up to but not including the upper bound).

A call to range(2,10) would return: 2, 3, 4, 5, 6, 7, 8, 9

A call to range(2,12,3) would return: 2, 5, 8, 11

Notice that I said, a couple times, that Python's range() function returns or generates a sequence. This is a relatively advanced distinction which usually won't be an issue for a novice. In older versions of Python range() built a list (allocated memory for it and populated with with values) and returned a reference to that list. This could be inefficient for large ranges which might consume quite a bit of memory and for some situations where you might want to iterate over some potentially large range of numbers but were likely to "break" out of the loop early (after finding some particular item in which you were interested, for example).

Python supports more efficient ways of implementing the same semantics (of doing the same thing) through a programming construct called a generator. Instead of allocating and populating the entire list and return it as a static data structure, Python can instantiate an object with the requisite information (upper and lower bounds and step/increment value) ... and return a reference to that.

The (code) object then keeps track of which number it returned most recently and computes the new values until it hits the upper bound (and which point it signals the end of the sequence to the caller using an exception called "StopIteration"). This technique (computing values dynamically rather than all at once, up-front) is referred to as "lazy evaluation."

Other constructs in the language (such as those underlying the for loop) can then work with that object (iterate through it) as though it were a list.

For most cases you don't have to know whether your version of Python is using the old implementation of range() or the newer one based on generators. You can just use it and be happy.

If you're working with ranges of millions of items, or creating thousands of different ranges of thousands each, then you might notice a performance penalty for using range() on an old version of Python. In such cases you could re-think your design and use while loops, or create objects which implement the "lazy evaluation" semantics of a generator, or use the xrange() version of range() if your version of Python includes it, or the range() function from a version of Python that uses the generators implicitly.

Concepts such as generators, and more general forms of lazy evaluation, permeate Python programming as you go beyond the basics. They are usually things you don't have to know for simple programming tasks but which become significant as you try to work with larger data sets or within tighter constraints (time/performance or memory bounds, for example).

[Update: for Python3 (the currently maintained versions of Python) the range() function always returns the dynamic, "lazy evaluation" iterator; the older versions of Python (2.x) which returned a statically allocated list of integers are now officially obsolete (after years of having been deprecated)].

Solution 3

for i in range(5):

is the same as

for i in [0,1,2,3,4]:

Solution 4

range(x) returns a list of numbers from 0 to x - 1.

>>> range(1)
[0]
>>> range(2)
[0, 1]
>>> range(3)
[0, 1, 2]
>>> range(4)
[0, 1, 2, 3]

for i in range(x): executes the body (which is print i in your first example) once for each element in the list returned by range(). i is used inside the body to refer to the “current” item of the list. In that case, i refers to an integer, but it could be of any type, depending on the objet on which you loop.

Share:
130,122

Related videos on Youtube

user211037
Author by

user211037

Updated on April 22, 2020

Comments

  • user211037
    user211037 about 4 years

    If I write

    for i in range(5):
          print i
    

    Then it gives 0, 1, 2, 3, 4
    Does that mean Python assigned 0, 1, 2, 3, 4 to i at the same time?
    However if I wrote:

    for i in range(5):
          a=i+1
    

    Then I call a, it only gives 5
    But if I add ''print a'' it gives 1, 2, 3, 4, 5
    So my question is what is the difference here?
    Is i a string or a list or something else?

    Or maybe can anyone help me to sort out:

    for l in range(5):
        #vs,fs,rs are all m*n matrixs,got initial values in,i.e vs[0],fs[0],rs[0] are known
        #want use this foor loop to update them
        vs[l+1]=vs[l]+fs[l]
        fs[l+1]=((rs[l]-re[l])
        rs[l+1]=rs[l]+vs[l]
    #then this code gives vs,fs,rs
    

    If I run this kind of code, then I will get the answer only when l=5
    How can I make them start looping?

    i.e l=0 got values for vs[1],fs[1],rs[1],
    then l=1 got values for vs[2],rs[2],fs[2]......and so on.
    But python gives different arrays of fs,vs,rs, correspond to different value of l

    How can I make them one piece?

    • PMARINA
      PMARINA about 9 years
      How come it doesn't work when I use any other variable name? Is 'i' something special?
    • Nicholas Hamilton
      Nicholas Hamilton almost 9 years
      You are calling 'a' after the loop had completed, therefore, 'a' holds the last value it was assigned in the loop
  • user211037
    user211037 over 14 years
    thanks for replay,its a great explanation, and plz bear me there is another question,in my third code, python gives different arays of fs,vs,rs, correspond to different value of l, how can I make them one pice? just update rows,thanks
  • user211037
    user211037 over 14 years
    thx for replay,however,in my third code, python gives different arays of fs,vs,rs, correspond to different value of l, how can I make them one pice? just update rows,thanks
  • Sam
    Sam over 6 years
    Does range() function get calculated every time the for loop is running or the first time it generates the iterator and the iterates through it?
  • Jim Dennis
    Jim Dennis over 6 years
    @SamiulSk: The range() function returns a generator object. That object maintains its own state (the current location in the range). Every call to next() on that object yields the next value (and updates its state accordingly). This is all true of Python generators in general.
  • Jim Dennis
    Jim Dennis about 6 years
    To be more specific the for loop implicitly calls next(iter_obj) where the "iter_obj" is some internally maintained reference to the object returned by the call to the range() function. In other words a for loop requires some sort of expression which evaluates into an iterable object. It then steps through that with next() (calling it's .__next__() method in Python3 or its .next() method in Python2).
  • samsamara
    samsamara about 5 years
    Not really with newer versions. The newer versions of python does not simply return a list when you call range(). See the ans of @Jim Dennis above reg how they work.