On 12/16/2013 09:49 AM, Rafael Knuth wrote:
Hej there,

number = 9
for element in range(2,9):
3 % 2 != 0:
My assumption is that the program should end the loop after the first
iteration again and it then should return True.

No. If it did that, it wouldn't be a *loop* at all, would it? The whole
reason loops (for and while) exist is to run the code repeatedly. If
they only ran once, no matter what, they would be useless.

Unless you exit a loop early (with a return, a break, or by raising an
exception) the loop will jump back to the beginning until such time as
the loop is completed. Then it will jump to the code following the loop.

So, here's a simple example:

for element in range(5):
     print(element)

With your assumption, you might think it will print 0, then stop. But
it doesn't. It prints 0, then 1, then 2, then 3, then 4. Each time
through the loop it jumps back to the beginning, gets the next value
from the range, and only when there are no more values to get does the
for-loop finish.

That's actually a good example. Let me explain what I feel confused about.
Print actually runs through the entire loop. But let's change the
program like this:

def RangeOfNumbers (n):
     for i in range(n):
         return i

print(RangeOfNumbers(5))

When you run this program, your result is:


0

So, return only returns the first value within the loop.
If you want the loop run over the entire range of values, you have to
change it like this:

def RangeOfNumbers (n):
     List = []
     for i in range(n):
         List.append(i)
     return List

print(RangeOfNumbers(5))


[0, 1, 2, 3, 4]

Let's get back to my original program:

def is_prime(number):
     for element in range(2, number):
         if number % element == 0:
             return False
     return True

I was assuming that the for loop ends after the first round, just like
in my first example above.
But as you explained the for loop iterates through the entire range
and only stops if a. there are no more values left to iterate through
or b. the condition is met (return False if number % element == 0).
That's the tiny little detail I am confused about: What does return
exactly do? Does it return only the first value within a loop or does
it iterate through all values within a loop? (unless a given condition
is met)

You are confused about the way the loop machinary works behind the stage. It is actually rather simple. Imagine a construction like this:

while has_next():
    item = next_item()
    # use item, eg:
    print(item)
    # pass to next item, if any

A for-loop in python is equivalent (and translates) to something conceptually similar to the above piece of code. has_next() say whether there is at least one more item in the stream. If yes, then next_item() provides this item. When you use a for-loop on an "iterable" object, meaning a stream of items (a list, range, etc), then python behind the stage constructs and uses the equivalent of has_next and next_item() functions for the kind of stream you want to loop across, and traverses the stream using a construct equivalent to the while-loop above. [The reality is slightly different: instead of has_next, it uses an exception to know when we have reached the end of the stream; but the conceptual principle remains.]

If you know about linked lists, then the principle is very similar to traversing a list:

while cell:                     # while (cell is not None)
    item = cell.value
    # use item
    cell = cell.next

If you want to dig into this even deeper. Here is an example of a class that would permit such traversal loop:

class ListStream:
    def __init__ (self, lst):
        self.lst = lst
        self.index = 0

    def has_next (self):
        return (self.index < len(self.lst))

    def next_item (self):
        item = self.lst[self.index]
        self.index += 1
        return item

Now, let us make a example list and its corresponding stream:

l = [1,3,5,7,9]
stream = ListStream(l)

Then, we can use the stream to traverse the list, for instance that way:

print("cubes:")
while stream.has_next():
    item = stream.next_item()
    print("    n:%d --> cube:%d" % (item, item*item*item))

Now, the stream has reached its end -- with index=5. To traverse the list again we could reset index=0 (or the stream class could provide a reset method), but in standard we would make a new stream. For all what we have done here by hand, python does an equivalent automagically behind the stage.

Denis
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to