Изменить размер шага для l oop в цикле - PullRequest
0 голосов
/ 12 января 2020

Есть ли способ, при котором я могу изменить размер шага a для l oop, пока я нахожусь в l oop?

Например, это не похоже на работу:

stepsize = 1.
for i in np.arange(0.,10.,stepsize):
   print i
   if i > 5:
      print "change"
      stepsize = 0.5

Выход:

0.0
1.0
2.0
3.0
4.0
5.0
6.0
change
7.0
change
8.0
change
9.0
change

Ответы [ 2 ]

1 голос
/ 12 января 2020

Проблема

Проблема в том, что когда вы объявляете ваше значение для l oop следующим образом:

for i in np.arange(0.,10.,stepsize):

Объект диапазона оценивается до до oop начинает выполняться, а затем никогда не изменяется. В качестве аналогии рассмотрим пример с целыми числами:

a = 0
b = a + 1 #b is evaluated using the *current* value of a, which is 0
a = 1
print(b) # 0 + 1 = 1

То же самое относится и к объявлению l oop, поскольку оно эквивалентно:

myRange = np.arange(0.,10.,stepsize)
for i in myRange:
    #...
    stepsize = 0.5 #will NOT affect the already initialized myRange variable!!

Простое решение

Следовательно, самое простое решение , на мой взгляд, просто использует while l oop и увеличивает ваш счетчик в соответствии с вашим условием if:

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
0 голосов
/ 12 января 2020

Не с np.arange, поскольку это дает вам полностью материализованный массив :

>>> r = np.arange(0., 1000000., 1)
>>> type(r)
<class 'numpy.ndarray'>
>>> r.__sizeof__()
8000048

Так что после его создания просто слишком поздно. Кроме того, он не имеет доступа к вашей переменной stepsize, поэтому не мог заметить, что вы ее изменили.

Сравните с range, который является легким объектом, который вычисляет значения на лету:

>>> r = range(0, 1000000, 1)
>>> type(r)
<class 'range'>
>>> r.__sizeof__()
24

(заметьте, я использую Python 3 ... вам действительно нужно присоединиться к нам. Не только потому, что в Python 2 эквивалент имеет уродливое имя xrange.)

Теперь ... этот range объект имеет атрибут step:

>>> dir(r)
['__bool__', '__class__', ..., 'count', 'index', 'start', 'step', 'stop']

Но это не позволит нам изменить его:

>>> r.step = 2
Traceback (most recent call last):
  File "<pyshell#46>", line 1, in <module>
    r.step = 2
AttributeError: readonly attribute

Вы можете использовать свой собственный Класс диапазона, поддерживающий такое изменение состояния, хотя:

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

Вывод:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...