3

I want to know if is it possible to change the value of the iterator in its for-loop?

For example I want to write a program to calculate prime factor of a number in the below way :

def primeFactors(number):
    for i in range(2,number+1):
        if (number%i==0)
            print(i,end=',')
            number=number/i 
            i=i-1 #to check that factor again!

My question : Is it possible to change the last two line in a way that when I change i and number in the if block, their value change in the for loop!

Update: Defining the iterator as a global variable, could help me? Why?

4
  • 3
    I expect someone will answer with code for what you said you want to do, but the short answer is "no"... when you change the value of number it does not change the value here: range(2,number+1) because this is an expression that has already been evaluated and has returned a list of numbers which is being looped over
    – Anentropic
    Sep 26, 2014 at 17:07
  • Nope, not with what you have written here. There are ways, but they'd be tricky to say the least.
    – mgilson
    Sep 26, 2014 at 17:07
  • Use a while loop instead. (Uglier but works for what you're trying to do.)
    – vanza
    Sep 26, 2014 at 17:08
  • There has been some discussion on the python-ideas list about a continue with statement to allow injection back into the iterator, but it is fairly simple to code a custom wrapper around an iterator that allows such behavior already.
    – chepner
    Sep 26, 2014 at 17:12
2

Short answer (like Daniel Roseman's): No

Long answer: No, but this does what you want:

def redo_range(start, end):
    while start < end:
        start += 1
        redo = (yield start)
        if redo:
            start -= 2

redone_5 = False
r = redo_range(2, 10)
for i in r:
    print(i)
    if i == 5 and not redone_5:
        r.send(True)
        redone_5 = True

Output:

3
4
5
5
6
7
8
9
10

As you can see, 5 gets repeated. It used a generator function which allows the last value of the index variable to be repeated. There are simpler methods (while loops, list of values to check, etc.) but this one matches you code the closest.

2

No.

Python's for loop is like other languages' foreach loops. Your i variable is not a counter, it is the value of each element in a list, in this case the list of numbers between 2 and number+1. Even if you changed the value, that would not change what was the next element in that list.

2
  • defining that iterator as a global variable couldn't help me? I remember it was possible in C++ to change the value of for-loop iterator in its block! Sep 26, 2014 at 17:37
  • 1
    @TheGoodUser : Please try to avoid modifying globals: there's almost always a better way to do things.
    – PM 2Ring
    Sep 26, 2014 at 21:13
2

The standard way of dealing with this is to completely exhaust the divisions by i in the body of the for loop itself:

def primeFactors(number):
    for i in range(2,number+1):
        while number % i == 0:
            print(i, end=',')
            number /= i

It's slightly more efficient to do the division and remainder in one step:

def primeFactors(number):
    for i in range(2, number+1):
        while True:
            q, r = divmod(number, i)
            if r != 0:
                break
            print(i, end=',')
            number = q
2

The only way to change the next value yielded is to somehow tell the iterable what the next value to yield should be. With a lot of standard iterables, this isn't possible. however, you can do it with a specially coded generator:

def crazy_iter(iterable):
  iterable = iter(iterable)
  for item in iterable:
    sent = yield item
    if sent is not None:
      yield None  # Return value of `iterable.send(...)`
      yield sent

num = 10
iterable = crazy_iter(range(2, 11))
for i in iterable:
  if not num%i:
    print i
    num /= i
    if i > 2:
      iterable.send(i-1)

I would definitely not argue that this is easier to read than the equivalent while loop, but it does demonstrate sending stuff to a generator which may gain your team points at your next local programming trivia night.

1

It is not possible the way you are doing it. The for loop variable can be changed inside each loop iteration, like this:

for a in range (1, 6):
    print a
    a = a + 1
    print a
    print

The resulting output is:

1
2

2
3

3
4

4
5

5
6

It does get modified inside each for loop iteration.

The reason for the behavior displayed by Python's for loop is that, at the beginning of each iteration, the for loop variable is assinged the next unused value from the specified iterator. Therefore, whatever changes you make to the for loop variable get effectively destroyed at the beginning of each iteration.

To achieve what I think you may be needing, you should probably use a while loop, providing your own counter variable, your own increment code and any special case modifications for it you may need inside your loop. Example:

a = 1
while a <= 5:
    print a
    if a == 3:
        a = a + 1
    a = a + 1
    print a
    print

The resulting output is:

1
2

2
3

3
5

5
6

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.