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

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[:].

Related

Python for loop weird bug [duplicate]

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]

Does Python automatically update variables whose value is another object? [duplicate]

This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 3 years ago.
Before asking, I read the accepted answer to the question "How do I pass a variable by reference?" and documentation linked in that same answer: "How do I write a function with output parameters (call by reference)?"
I have a related question: Does Python automatically synchronize a variable whose value is a reference to another object? In other words, if I assign an object as the value of a variable, is the variable updated whenever the object is modified?
I have a specific problem where it appears that Python updates the value of a variable with an object as its value without any code explicitly triggering an update. I created a function that was supposed to be part of a solution to the ROT13 (rotate right 13 times) problem: shift an array to the right 13 times. Here is the function's code:
array = [0, 1, 2, 3, 4, 5]
print(array)
backup = array
#backup = [n for n in array]
for i in range( 1, (len(backup)) ):
array[i] = backup[i - 1]
array[0] = backup[-1]
backup = array
print(array)
The output of that code is wrong: [0, 0, 0, 0, 0, 0] .
However, when I replace line 3 (backup = array) with backup = [n for n in array], the answer is correct: [5, 0, 1, 2, 3, 4]
I inferred that whenever the for-loop executed, the value of backup was updated because its value is inherently a reference to the object array. It appears to me that when array[1] was assigned the value zero, backup[1] was also assigned zero instead of holding the value 1. Because of that, the for-loop simply assigned the value zero to every other variable in backup thru array.
If I instead assigned backup to a list object distinct from array using backup = [n for n in array], modifying array would not modify backup.
What is the actual cause of this behavior?
In your example backup and array are both references to the same object. That is clear with this code example:
>>> array=[1,2,3,4]
>>> backup=array
>>> id(array)
4492535840
>>> id(backup)
4492535840
So your code is equivalent to this:
array = [0, 1, 2, 3, 4, 5]
print(array)
for i in range( 1, (len(array)) ):
array[i] = array[i - 1]
array[0] = array[-1]
print(array)
Does that help?
There’s no synchronization going on. Instead, there’s only one list. Both variables reference that same list – you can think of the variables as pointing to it or as tagging it, if that helps. You perform operations on values and not on variables, so given that there’s only one list, all of the operations change it and read changes back from the same one.

Why does .pop() eventually stop and not keep removing items from a list until the list is empty? [duplicate]

This question already has answers here:
problem Deleting list items in a for loop (python) [duplicate]
(4 answers)
Why does Python skip elements when I modify a list while iterating over it?
(8 answers)
Closed 3 years ago.
I am trying to build a card game hand simulator.
I want to be able to shuffle a list of cards (import random I assume) and then remove cards off the top of the deck and put them into my hand. I want to be able to draw as long as I like.
The PROBLEM is that when I use .pop() to do this, it will remove elements from a randomized list for a few lines, but then eventually stop and then just leave 2 items left in the list. When I look up the documentation, it says .pop() by default removes the item at position 0, so I don't know why it doesn't just continue.
Right now I am trying to use the .pop() method. I am new to python so there may be a better way, I just don't know if there could be a better method. Regardless, I am trying to understand why .pop() didn't solve this problem and the documentation isn't exactly helping.
'''the for-loop is supposed to shuffle my cards, and then keep plucking one off of the top until there are no more cards in the deck'''
import random
hand = [1,2,3,4,5]
random.shuffle(hand)
for i in hand:
card = hand.pop(0)
print(card)
print(hand)
What I actually get:
1
[4, 5, 3, 2]
4
[5, 3, 2]
5
[3, 2]
What I would LIKE to get:
1
[4, 5, 3, 2]
4
[5, 3, 2]
5
[3, 2]
3
[2]
2
[]
General explanation:
You're modifying a list at the same time you're iterating over its contents. Bad things happen when you do that.
Slightly more technical explanation:
The for loop for i in hand only evaluates hand once, at the start of the loop . But each time through the loop you're removing items from the list, so the results of the for loop are now out of sync with the current state of the list.
Try this instead:
import random
hand = [1,2,3,4,5]
random.shuffle(hand)
while hand:
card = hand.pop(0)
print(card)
print(hand)

What is Callback in python? [duplicate]

This question already has answers here:
How can I provide a "callback" to an API?
(5 answers)
Closed 5 years ago.
I want to create a list of squares of even numbers by creating a list, applying the callback functions to each element of the list and puts the result in a list. But how do I implement callback in the first place?
In this case I think you are looking for the map builtin. It takes a function and a list and then applies that function on the list storing each result as it goes. For example:
def square(x):
return x * x
list(map(square, [1, 2, 3, 4]))
>>> [1, 4, 9, 16]
Note that we need to cast the result of map back to a list since it returns a map object.

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

Categories

Resources