Reputation: 164
is there a method where I can change the stepsize of a for loop, while I am in the loop?
E.g. this doesn't seem to work:
stepsize = 1.
for i in np.arange(0.,10.,stepsize):
print i
if i > 5:
print "change"
stepsize = 0.5
Output:
0.0
1.0
2.0
3.0
4.0
5.0
6.0
change
7.0
change
8.0
change
9.0
change
Upvotes: 0
Views: 3493
Reputation: 6912
The issue is that when you declare your for loop as such:
for i in np.arange(0.,10.,stepsize):
The range object gets evaluated before the loop starts executing, and then never gets modified. As an analogy, consider this integer example:
a = 0
b = a + 1 #b is evaluated using the *current* value of a, which is 0
a = 1
print(b) # 0 + 1 = 1
The same applies for this for loop declaration, as it is equivalent to:
myRange = np.arange(0.,10.,stepsize)
for i in myRange:
#...
stepsize = 0.5 #will NOT affect the already initialized myRange variable!!
Therefore, the easiest solution is, in my opinion, to simply use a while loop, and increment your counter according to your if condition:
i = 1.
while i < 10:
print i
if i > 5:
print "change"
i += 0.5 #condition met, increment by 0.5 instead of 1
else:
i += 1 #otherwise, increment by 1
Upvotes: 3
Reputation: 27629
Not with np.arange
, as that gives you a fully materialized array:
>>> r = np.arange(0., 1000000., 1)
>>> type(r)
<class 'numpy.ndarray'>
>>> r.__sizeof__()
8000048
So after it is created, it's simply too late. Also, it has no access to your stepsize
variable, so couldn't notice that you changed it.
Compare to range
, which is a lightway object that calculates values on the fly:
>>> r = range(0, 1000000, 1)
>>> type(r)
<class 'range'>
>>> r.__sizeof__()
24
(Note I'm using Python 3... you should really join us. Not just because in Python 2 the equivalent has the ugly name xrange
.)
Now... that range
object does have a step
attribute:
>>> dir(r)
['__bool__', '__class__', ..., 'count', 'index', 'start', 'step', 'stop']
But it won't let us change it:
>>> r.step = 2
Traceback (most recent call last):
File "<pyshell#46>", line 1, in <module>
r.step = 2
AttributeError: readonly attribute
You could use your own range class supporting such a state change, though:
class Range:
def __init__(self, start, stop, step):
self.current = start
self.stop = stop
self.step = step
def __iter__(self):
while self.current < self.stop:
yield self.current
self.current += self.step
for i in (r := Range(0, 10, 1)):
print(i)
if i > 5:
print("change")
r.step = 0.5
Output:
0
1
2
3
4
5
6
change
6.5
change
7.0
change
7.5
change
8.0
change
8.5
change
9.0
change
9.5
change
Upvotes: 1