Use zip with slicing:
>>> for x,y in zip(data[::2], data[1::2]):
... print(f"{x}\t{y}")
...
300 5
400 7
500 4
>>>
Or you can use this cheeky construction*:
>>> for x,y in zip(*[iter(data)]*2):
... print(f"{x}\t{y}")
...
300 5
400 7
500 4
The above should give you a taste of the plethora of iterating constructs python offers. However, I suggest sticking with basic looping constructs, such as:
>>> for i in range(0, len(data) - 1, 2):
... print(data[i],data[i+1])
...
300 5
400 7
500 4
Note, learn to prefer for-loops over while loops. They are less error prone once you get the hang of them. You can do a lot with range. However, here is the equivalent while-loop:
i = 0
while i < len(data) - 1:
print(data[i], data[i+1])
i += 2
*Note, although I don't usually use stuff this arcane because I value readability and simplicity, but it is sort of a classic Pythonism. It can be generalized thusly:
>>> def iter_by_n(iterable, n):
... return zip(*[iter(iterable)]*n)
...
>>> list(iter_by_n(range(9), 3))
[(0, 1, 2), (3, 4, 5), (6, 7, 8)]
However, it will give you only up until the last whole partion:
>>> list(iter_by_n(range(10), 3))
[(0, 1, 2), (3, 4, 5), (6, 7, 8)]
>>> list(iter_by_n(range(11), 3))
[(0, 1, 2), (3, 4, 5), (6, 7, 8)]
>>> list(iter_by_n(range(12), 3))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11)]
This is often the behavior you want, but you can also fill in the partions using itertools.zip_longest with whatever default you want:
>>> from itertools import zip_longest
>>> def iter_by_n(iterable, n, fillvalue=None):
... return zip_longest(*[iter(iterable)]*n, fillvalue=fillvalue)
...
>>> list(iter_by_n(range(10), 3))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, None, None)]
>>> list(iter_by_n(range(10), 3, fillvalue='FOO'))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 'FOO', 'FOO')]
>>> list(iter_by_n(range(11), 3, fillvalue='FOO'))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 'FOO')]
>>> list(iter_by_n(range(12), 3, fillvalue='FOO'))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11)]
>>>
indexwith2, not1.index += 2should rly fix it.