python a=[[],]*10 [duplicate] - python

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Python list confusion
When I write a simple python script, I define a new list as follows:
A=[[],]*10
What I wanna do is just initialize a list whose length is 10 and each element is a empty list.
And when I do something like:
A[0].append(["abc",])
I just wanna append this ["abc",] to A[0], and it turn out to be that every elements in A is appended with ["abc",]
I know this probably due to my initialization (A=[[],]*10) . I just want to know why this happened.

Your expression A=[[]]*10 is equivalent to:
a = []
A = [a]*10
This means that A consists of 10 references to one and the same list.

You are creating a list with 10 references to the same empty list.
You should use a list comprehension instead:
A = [[] for _ in range(10)]
In a list comprehension, you create a new list for every iteration through the loop. If you are using python 2, you should use xrange instead of range (although with only 10 elements that won't make much difference).

All the empty lists are references to the same object.

Related

Iterating and changing elements in a list in Python [duplicate]

This question already has answers here:
Can't modify list elements in a loop [duplicate]
(5 answers)
Closed 4 years ago.
I'm supposed to find the largest number in a list, and then change all the elements of the list to that number. But when I print the output after the iteration, it still hasn't changed. What am I doing wrong please ?
Ar =[5,4,11]
ArMax = max(Ar)
for i in Ar:
i = ArMax
print(Ar)
The list doesn't change because you've done nothing to change the list. Your list is Ar -- where have you assigned a new value to anything in that list? Nowhere. All you did was to create a local variable to take on the values in Ar, and then change the value of that variable. You never touched the original list. Instead, you have to change the list elements themselves, not their copies. Keeping close to your present code:
for i in range(len(Ar)):
Ar[i] = ArMax
Another way would be to create a new list with those items in it, and simply replace the original list all at once:
Ar = [ArMax] * len(Ar)
This looks to see how long the current list is with len(Ar). Then it takes a one-element list with the max value and replicates it that many times. That new list becomes the new value of Ar.
i = ArMax does not actually assign values to the list because the values of i are copies of the elements in the list. If you want to fix this, try:
for i in xrange(len(Ar)):
Ar[i] = ArMax

Changing list while iterating [duplicate]

This question already has answers here:
Modifying a list while iterating over it - why not? [duplicate]
(4 answers)
Closed 6 years ago.
I've found a python puzzle and can't find out why it works.
x = ['a','b','c']
for m in x:
x.remove(m)
and after this loop x = ['b'].
But why?
As far as I understand for keyword implicitly creates iterator for this list. Does .remove() calls __next__() method so b is skipped? I can't find any mentions of it but this is my best guess.
Here you are iterating over the original list. On the first iteration, you removed the 0th index element i.e. a. Now, your list is as: ['b','c']. On the second iteration your for loop will access the value at index 1 but your index 1 has value c. So the c is removed. Hence resultant list will be ['b'].
In order to make it behave expectedly, iterate over the copy of the list, and remove the item from original list. For example:
x = ['a','b','c']
for m in list(x): # <-- Here 'list(x)' will create the copy of list 'x'
# for will iterate over the copy
x.remove(m)
# updated value of 'x' will be: []
Note: If it is not for demo purpose and you are using this code for emptying the list, efficient way of emptying the list will be:
del x[:]

Python - Extending a list directly results in None, why? [duplicate]

This question already has answers here:
How do I concatenate two lists in Python?
(31 answers)
Why do these list operations (methods: clear / extend / reverse / append / sort / remove) return None, rather than the resulting list?
(6 answers)
Closed 5 months ago.
x=[1,2,3]
x.extend('a')
Output:
x is [1,2,3,'a']
But when I do the following:
[1,2,3].extend('a')
Output:
None
Why does extend work on a list reference, but not on a list?
2nd Part:
I found this because I was trying to append a listB to a listA while trying to extend listC to listB.
listA.append([listB[15:18].extend(listC[3:12])])
Supposing lists cannot be directly appended / extending. What is the most popular work around form for resolving this issue?
list.extend modifies the list in place and returns nothing, thus resulting in None. In the second case, it's a temporary list that is being extended which disappears immediately after that line, while in the first case it can be referenced via x.
to append a listB to a listA while trying to extend listC to listB.
Instead of using extend, you might want to try this:
listA.append(listB[15:18] + listC[3:12])
Or do it in multiple simple lines with extend if you want to actually modify listB or listC.
extend will extend list it self. Return type of that method is None
If you want to union 2 list and add that list to another list then you have to use another way to add.
listB[15:18] = listC[3:12]
listA.extend(listB)

How do I create a list of independent sets in python? [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Why does this code for initializing a list of lists apparently link the lists together? [duplicate]
(1 answer)
Closed 8 years ago.
I have a list that needs to contain a variable number of independent sets.
When I run the following piece of code, I want to add the string "testing" to only the first set.
numberOfSets = 3
test = [set()]*numberOfSets
test[0].add("testing")
print test
However, when I print test, it shows three identical sets that all contain testing. How can I set up my list so I can separately access each set?
When you do [set()]*3, you create three sets that reference the same object, thus when you change one value, the others change. Use a list comprehension here instead:
>>> numberOfSets = 3
>>> test = [set() for _ in xrange(numberOfSets)]
>>> test[0].add("testing")
>>> print test
[set(['testing']), set([]), set([])]
You can do
test = [set() for _ in xrange(numberOfSets)] # use 'range' in Python 3.x
[set()]*x creates a list with x of the same set instance, whereas the comprehension above creates a new, independent set on each iteration, as desired.
In general, you should be very cautious whenever you multiply lists whose elements are mutable.

How to get a copy from a list? [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 9 years ago.
I am trying to get an element from list and make some change on this element (which is also a list). Weirdly, the change applied on the previous list. Here is my code:
>>>sentences[0]
['<s>/<s>',
'I/PRP',
'need/VBP',
'to/TO',
'have/VB',
'dinner/NN',
'served/VBN',
'</s>/</s>']
>>>sentence = sentences[0]
>>>sentence.insert(0,startc); sentence.append(endc)
>>>sentences[0]
['<s>/<s>',
'<s>/<s>',
'I/PRP',
'need/VBP',
'to/TO',
'have/VB',
'dinner/NN',
'served/VBN',
'</s>/</s>'
'</s>/</s>']
It is like I just got a pointer to that element, not a copy
You do get a "pointer", in fact. Lists (and any mutable value type!) are passed around as reference in Python.
You can make a copy of a list by passing it to the list() object constructor, or by making a full slice using [:].
a = [1,2,3]
b = a
c = list(a)
d = a[:]
a[1] = 4 # changes the list referenced by both 'a' and 'b', but not 'c' or 'd'
You're exactly right! In Python, when you pass a list as an argument to a function, or you assign a list to another variable, you're actually passing a pointer to it.
This is for efficiency reasons; if you made a separate copy of a 1000-item list every time you did one of the aforementioned things, the program would consume way too much memory and time.
To overcome this in Python, you can duplicate a one-dimensional list using = originalList[:] or = list(originalList):
sentence = sentences[0][:] # or sentence = list(sentences[0])
sentence.insert(0,startc)
sentence.append(endc)
print(sentence) # modified
print(sentences[0]) # not modified
Consider using list comprehension if you need to duplicate a 2D list.

Categories