[Tutor] Prime Numbers
spir
denis.spir at gmail.com
Mon Dec 16 12:03:51 CET 2013
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
More information about the Tutor
mailing list