Why does the value of range(len(whole)/2) not change after whole is modified? And what do you call range(len...) value in for-loop?
whole = 'selenium'
for i in range(len(whole)/2):
print whole
whole = whole[1:-1]
output:
selenium
eleniu
leni
en
The range() produces a list of integers once. That list is then iterated over by the for loop. It is not re-created each iteration; that'd be very inefficient.
You could use a while loop instead:
i = 0
while i < (len(whole) / 2):
print whole
whole = whole[1:-1]
i += 1
the while condition is re-tested each loop iteration.
The range function creates a list
[0, 1, 2, 3]
And the for loop iterates over the value of the list.
The list is not recreated each and every time
But this is not the case in normal list
wq=[1,2,3]
for i in wq:
if 3 in wq:
wq.remove(3)
print i
1
2
Related
This python code is giving certain output someone please explain logic behind it.
l = [1,2,3,4,5]
for l[-1] in l:
print(l[-1])
output for this code is
1
2
3
4
4
You iterate through the list while assigning each value to the last value of list instead of the temporary i that we always use. So you can print every value of list except the last one cause second last one overwrites it and that's why the second last is printed twice.
Now understand for-loop behaviour in python. lets consider the following for loop:
for {val} in l: #curly braces only for the post, please do not write in python
print(val)
What python does is launch an iterator over the list l, and for every value in the list, the variable in the {} is assigned the value and prints it -> 1 2 3 4 5
now what has happened in your code is the {} contain a reference, to the iterating list itself, specifically to -1 index of the list, aka, the last element
so the for-loop still does the exact same thing, goes over the list from left to right, but also assigns the value to the last position of the same list it is iteration over.
DRY RUN:
outside for-loop: l= [1,2,3,4,5]
iteration 1: l= [1,2,3,4,1]
iteration 2: l= [1,2,3,4,2]
iteration 3: l= [1,2,3,4,3]
iteration 4: l= [1,2,3,4,4]
now for last iteration, it is iterating over and assigning to the same position, so it outputs 4 again.
TLDR:
instead of using a temp variable in the for loop, we are using a postion in our list itself, and actually modifying it as a result every iteration.
So, I am trying something simple. I am trying to go through a list, which, once sorted, I can see if the next number along is higher than the previous.
If this is so, I can add it into a new list:
def longestRun(L):
'''
assume L is not empty
'''
new_list=[]
list_place=0
# we then need to iterate along the sorted List L
print L[list_place]
print L[list_place+1]
if L[list_place] < L[list_place+1]
new_list+=L[list_place]
list_place+=1
L = [1, 2, 3]
list_place = 0
new_list = []
while list_place < len(L)-1:
print L[list_place]
if L[list_place] < L[list_place+1]:
new_list.append(L[list_place])
list_place+=1
print len(new_list)
To iterate, first you need a loop statement, like while. Second, if you don't increment list_place every time you iterate, once if statement evaluates to false, it goes into loop forever.
can someone explain me the loop below:
for item in aList[start:end:1]:
aList[aList.index(item)],aList[aList.index(item)+1] = aList[aList.index(item)],aList[aList.index(item)+1]
Let s say aList = [5,2,3,6,1]. the first iteration the index would 0. in the second would be again 0 and after will be increased to 2. Thus it will choose [5,2] and will continue with [2,5] [3,6]....
Why is that and what is the right way to do this?
UPDATE: The above is just an example of a specific behavior I wanted to understand. the actual code tries to implement a coctail sort algorithm.
The actual code is like that
if f == 1:
for d in area[start:end:f]:
print area,f ,d,area[area.index(d)+1],area.index(d)+1
if d > area[area.index(d)+1]:
tmp = area.index(d)
area[tmp], area[tmp+1] = area[tmp+1],area[tmp]
area=area
end -= 1
f = ~f + 1
if f == -1:
for d in area[end:start:f]:
print area,f,d,area[area.index(d)-1],area.index(d)-1
if d < area[area.index(d)-1]:
tmp = area.index(d)
area[tmp], area[tmp-1] = area[tmp-1], area[tmp]
area=area
start += 1
f = ~f + 1
As John said, it is a bad idea to mutate a list whilst looping over it. Instead create a copy of the list and change the data in the copy of the list. However it's also unclear what you are trying to achieve so if you specify that there might be a better way to do it.
Before diving into the problem, it's worth noting there are a couple issues with the code as written.
start and end aren't defined
The assignment in the for-loop doesn't actually swap the order
Those things aside, the algorithm fails, because you iterate over every item. I'll go through 2 iterations to show you why that's so.
Let's use your example:
aList = [5,2,3,6,1]
First iteration:
item = 5
aList.index(5) = 0
so, we're going to swap aList[0] and aList[1]
at the end of the iteration, aList = [2,5,3,6,1]
Second iteration:
item = 2
Wait, why 2? Because the slice operation creates a new list that we're iterating over, and that list has the original order.
aList.index(2) = 0
so, we're going to swap aList[0] and aList[1]... again.
at the end of the iteration, aList = [5,2,3,6,1]... which is the original order.
And so on
On the third iteration, we'll wind up swapping the 3rd and 4th items. And on the fourth iteration of the loop, we'll swap them again.
You can verify this is the case by adding a print statement to your for-loop: print aList.
So how do you fix it?
You can get around this behavior by iterating over every other item, instead of every item. Try changing the slice stride (step) to 2, instead of 1.
Consider the following snippet of Python code:
x = 14
for k in range(x):
x += 1
At the end of execution, x is equal to 28.
My question: shouldn't this code loop forever? At each iteration, it checks if k is less than x. However, x is incremented within the for loop, so it has a higher value for the next comparison.
range(x) is not a "command". It creates a range object one time, and the loop iterates over that. Changing x does not change all objects that were made using it.
>>> x = 2
>>> k = range(x)
>>> list(k)
[0, 1]
>>> x += 1
>>> list(k)
[0, 1]
no, range(x) will return a list with the items[0,1,2,3,4,5,6,7,8,9,10,11,12,13] these items will be iterated. Each time that the loop body gets evaluated x's value change but this does not affects the list that was already generate.
in other words the collection that you will be iterating will be generated only one time.
It's because python for in loop have different behavior compared to for (in other languages):
range(x) is not executed in every iteration, but at first time, and then for in iterate across its elements.
If you want to change the code to run an infinite loop you can use a while instead (and in that case range(x) is pointless).
The for loop in python is not an iterator, but rather iterates over a sequence / generator i.e. any form of iterable.
Considering this, unless the iterable is infinite, the loop will not be infinite. A sequence cannot be infinite but you can possibly create/utilite an infinite generator. One possibility is to use itertools.count which generates a non-ending sequence of numbers starting from a specified start with a specified interval.
from itertools import count | for(;;) {
for i in count(0): | //An infinite block
#An infinite block | }
Alternatively, you can always utilize while loop to create a classical infinite loop
while True:
#An infinite block
I am quite new to Python 2.7 so I had a couple of questions regarding using for loops to while loops.
For example: I am writing this definition
def missingDoor(trapdoor,roomwidth,roomheight,step):
safezone = []
hazardflr = givenSteps(roomwidth,step,True)
safetiles = []
for m in hazardflr:
safetiles.append((m,step))
i = 0
while i < len(safetiles):
nextSafe = safetiles[i]
if knownSafe(roomwidth, roomheight, nextSafe[0], nextSafe[1]):
if trapdoor[nextSafe[0]/roomwidth][nextSafe[0]%roomwidth] is "0":
if nextSafe[0] not in safezone:
safezone.append(nextSafe[0])
for e in givenSteps(roomwidth,nextSafe[0],True):
if knownSafe(roomwidth, roomheight, e, nextSafe[0]):
if trapdoor[e/roomwidth][e%roomwidth] is "0" and (e,nextSafe[0]) not in safetiles:
safetiles.append((e,nextSafe[0]))
i += 1
return sorted(safezone)
I am trying to turn all the for loops to a while loops, so this is currently what I have written so far. I actually dont know if we say "While e in " works near the middle of the code. But using the while loop rules, will this code do the same as the for loop one?
safezone = []
hazardflr = givenSteps(roomwidth,step,True)
safetiles = []
m=0
while m < hazardflr:
safetiles.append((m,step))
i = 0
while i < len(safetiles):
nextSafe = safetiles[i]
if knownSafe(roomwidth, roomheight, nextSafe[0], nextSafe[1]):
if trapdoor[nextSafe[0]/roomwidth][nextSafe[0]%roomwidth] is "0":
if nextSafe[0] not in safezone:
safezone.append(nextSafe[0])
e=0
while e in givenSteps(roomwidth,nextSafe[0],True):
if knownSafe(roomwidth, roomheight, e, nextSafe[0]):
if trapdoor[e/roomwidth][e%roomwidth] is "0" and (e,nextSafe[0]) not in safetiles:
safetiles.append((e,nextSafe[0]))
e+=1
i += 1
m+=1
return sorted(safezone)
thanks for any advice or help!
No, your code isn't identical.
While they look similar, for item in list and while item in list will do wildly different things.
for item in list is a syntactic way of saying for every item in the list - do something with is.
while item in list is different - a while loop iterates as long as the condition is true. The condition in this case being item in list. It doesn't update the item each iteration and if you never change what item or list are, it might never terminate. Additionally, if any given item isn't in the list it may terminate prematurely.
If you want to iterate through a list and keep a count, using while is the wrong way to go about it. Use the enumerate() function instead.
enumerate() takes a list, and returns a list of tuples, with each item from the list in order with its index, like so:
for i,m in enumerate(hazardflr):
safetiles.append((m,step))
This small change means you no longer have to track your indices manually.
If you are iterating through every item in a list in Python - use for that's what it is designed to do.
It depends on exactly what givenSteps returns, but in general, no. for x in foo evaluates foo once and then assigns x to be each element of foo in turn. while x in foo: ... x += 1, on the other hand, evaluates foo on every iteration and will end early if foo is not a contiguous sequence. For example, if foo = [0, 1, 2, 5, 6], for will use every value of foo, but while will end after 2, because 3 is not in foo. while will also differ from for if foo contains any non-integral values or values below the starting value.
while aList:
m= hazardflr.pop()
# ...
should be roughly equivelent to your other loop