Python for loop weird bug [duplicate] - python

This question already has answers here:
Why can I use a list index as an indexing variable in a for loop? [duplicate]
(6 answers)
Are for-loop name list expressions legal?
(2 answers)
Closed last year.
So in a quiz, I have given the question what the execution of this block of code gives (The one under).
a = [0, 1, 2, 3]
for a[0] in a:
print(a[0])
I had selected error but to my surprise, it actually works and is able to print all the elements inside the list. But how?
firstly the element getting variable (usually i) is shadowing the actual variable on top of that we are getting the first element inside a number so how is it working.

a[0] is type of a so it can be used to iterate over the array but as in look you are assigning value in a[0] it's value will change to last element of the array.
a = [0,1,2,3]
for a[0] in a:
print(a[0]
Will result in:
0
1
2
3
But now printing a will give you modified array:
print(a)
[3, 1, 2, 3]

Related

For loop is not executing as expected, sequence matters so can't use set() here [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 4 years ago.
I used a for loop to remove the duplicates in a list from the left side. For example, [3,4,4,3,6,3] should be [4,6,3]. And also the sequence cannot be changed, that's why I cannot use a set here. If I use set() here, the result would be [3,4,6].
def solve(arr):
for i in arr:
if i in arr[arr.index(i)+1:]:
arr.remove(i)
return arr
solve([1,2,1,2,1,2,3])
It should return [1,2,3]. Instead, I got [2,1,2,3]. I viewed the visualized execution of the code, and it seems when python got to the item '2' the second time, meaning when the arr is mutated to be [2,1,2,3], it just suddenly stopped iteration from the for loop and returned the list as it is. When it should detect there is still another '2' in the list. Please help
You can use set for this:
a = [1,2,1,2,1,2,3]
b = set(a)
Then b will be:
{1,2,3}
You can try this way:
def solve(arr):
another_arr = []
for i in arr:
if i in another_arr:
another_arr.remove(i)
another_arr.append(i)
else:
another_arr.append(i)
return another_arr
print(solve([1, 2, 1, 2, 1, 2, 3]))

element modification during python list iteration [duplicate]

This question already has answers here:
Change value of currently iterated element in list
(3 answers)
Scope of python variable in for loop
(10 answers)
Closed 4 years ago.
Could anyone, please, explain what exactly happens in the following code to the "element" during iteration?
array = [2,3,4]
for element in array:
element = 3
print(array)
>>>[2, 3, 4]
Output is [2, 3, 4]
instead of [3, 3, 3]
Did I understand it correctly that when using "for element in l" syntax, we can only reference but not modify each element of an array of what does happen here?
P.S. I've seen the question named "why shouldn't you iterate like 'for element in array' ", but I couldn't find that one, so I asked it in this way. Seems like I found one of the disadvantages of iterating in this way. Please, redirect me to the mentioned question if possible.
Explanation
In the above example any changes to variable element in the loop is not possible.
Code
To get your expected output try this:
array = [2,3,4]
for i in range(len(array)):
array[i] = 3
print(array)
When the iteration start element variable already has the current value in the array. when you assign 3 to it it will contain it until the next iteration when it will again take the current value of the array and so on.
To get [3, 3, 3] you need to do it as the following:
array = [2,3,4]
for i in range(0,len(array)):
array[i]=3
print(array)
That's because element is a local variable in the scope of the for loop.
Run this snippet. I hope it can be self-explanatory (I used e instead of element), also I used enumerate to get the index:
array = [2,3,4]
for i, e in enumerate(array):
print('i =', i, 'e =', e)
e = 100
print('e = 100-->','e =', e, 'but array[i]=',array[i])
array[i] = e
print('array[i] = e --> array[i]=',array[i])
print('-'*10)
print(array) #=> [100,100,100]
Quick explanation
e and i are local variables which receive the value of the element and the index of the array at each iteration.
Inside the loop you can change the value of e but it doesn't affect the the array. To change the value inside the array it is required to access it by index (array[i]).

Appending a global list to a global list? [duplicate]

This question already has answers here:
Why does foo.append(bar) affect all elements in a list of lists?
(3 answers)
Value changes in new list impact previous list values, within a list of lists [duplicate]
(2 answers)
Python append behaviour odd? [duplicate]
(3 answers)
Closed 4 years ago.
I have written following code for solving the n-Queens problem where we have to find all possible legal (non-attacking) placements of n queens in an n*n chessboard. The code uses the standard backtracking solution.
Here the method n_queens uses the helper method solve_n_queens which uses recursion. The outer method just initializes global lists result & col_placement and calls the helper method.
def n_queens(n):
def solve_n_queens(row):
if row == n: # all queens are legally placed
result.append(list(col_placement))
return
for col in range(n):
# check if new queen is either 1) in same column or 2) same diagonal with any previously placed queen
if all(abs(col-c) not in (0, row-r)
for r, c in enumerate(col_placement[:row])):
col_placement[row] = col
solve_n_queens(row+1)
result, col_placement = [], [0] * n # result is empty initially; [0] * n means no queen is placed
solve_n_queens(0)
return result
This gives erroneous output for n_queens(4)
[[3, 1, 2, 1], [3, 1, 2, 1]]
However it is not an algorithmic bug because just altering the 4th line result.append(col_placement) to result.append(list(col_placement)) mysteriously gives the correct output
[[1, 3, 0, 2], [2, 0, 3, 1]]
What I don't grok is when col_placement is already a list, why do we need to call the list method?
The problem is that without using list you are appending a reference to the same and only list col_placement you are working with (as you can see the results are not only wrong, but they are also the same). Using list creates a new copy (a instant snapshot of col_placement) that will not be modified when col_placement does as you keep going through the rest of the program.
So essentially list(col_placement) is the same as col_placement.copy() or col_placement[:].

Why doesn`t list[:][0] get me the first row of the list? [duplicate]

This question already has answers here:
Understanding slicing
(38 answers)
Closed 6 years ago.
For the following:
list=[[2, 3, 5], [7, 8, 9]]
Why does [list[0][0], list[1][0]] represent the first row ([2, 7]), but the command list[:][0] or list[0:2][0] returns the first column ([2, 3, 5])?
The way I see it list[:][0] should get all the possible values for the first parameter (that is 0 and 1) and 0 for the second, meaning it would return the first row. Instead what it does is return the first column and I can't understand why.
In python, the [a:b:c] syntax creates a new list. That is,
list = [1,2,3]
print(list[:])
is going to print a list, not a value.
Therefore, when you say list[:][0] you are making a copy of the original list (list[:]) and then accessing item 0 within it.
Of course you know, item 0 of the original list (list[0]) is another list.
I think you want:
[sl[0] for sl in list]
Elaboration:
This is called a "comprehension." It is a compact special syntax for generating lists, dicts, and tuples by processing or filtering other iterables. Basically {..}, [..], and (..) with an expression inside involving a for and optionally an if. Naturally, you can have multiples (like [x for x in y for y in z]) of the for, and multiples of the if.
In your case, it's pretty obvious you want a list. So []. You want to make the list by taking the first item from each sublist. So [sl[0] for sl in list].
Here's a more-detailed article: http://carlgroner.me/Python/2011/11/09/An-Introduction-to-List-Comprehensions-in-Python.html

Retrieving list elements in Python [duplicate]

This question already has answers here:
Understanding slicing
(38 answers)
Closed 6 years ago.
I'm a beginner attempting to learn Python. I am familiarising myself with the list data type; I've defined the following list:
>>> numbers = [1, 2, 3, 4]
Typing:
>>> numbers[0]
1
>>> numbers[1]
2
>>> numbers[2]
3
>>> numbers[3]
4
Given this, why do I get the following when I attempt to retrieve the following list elements:
>>> numbers[0:3]
[1, 2, 3]
Why isn't the list element '4' included in the response from the interpreter?
Thank you for your help.
Slice notation does not include the last element (similar to the range() function in that respect). If you want to include the last element, simply omit an index. Also, the default start is the beginning, so you don't need 0 there either:
>>> numbers[:]
[1, 2, 3, 4]
Note that this is a (shallow) copy of numbers. If you save a reference to it, you can mutate it without affecting the original numbers.
That's how slicing works in Python. To quote a tutorial:
Note how the start is always included, and the end always excluded.
This makes sure that s[:i] + s[i:] is always equal to s.
The example uses a string, but slicing works the same way with lists.
numbers[0:3] list from 0 up to 3 but 3 is excluded (like range(0,3))

Categories

Resources