The append() method issue of list in Python3 - python

for example,i got a list:
mylist = [1,2,3]
we all know append() can add a new item at the end of the list like that:
mylist.append(4)
now the mylist is [1,2,3,4]
my issue is what happened when mylist append itself????
mylist.append(mylist)
at first i think it will look like this:
[1,2,3,4,[1,2,3,4]]
but when i print it, output is [1,2,3,4,[...]],so i print the mylist[5] and it's same to the mylist:[1,2,3,4,[...]]
so you can loop the last item of list endless,and the last item always be the same to original mylist!!!!!
anyone can tell me why is that????????

Because you aren't appending a copy of the list, but the actual list object itself. Consider this program:
mylist = [1,2,3,4]
mylist.append(mylist)
assert id(mylist) == id(mylist[4])
The final item of the list is a reference to the list itself, so you have a fully recursive, self-referential data structure.
If you want the result [1,2,3,4,[1,2,3,4]], then you need to append a copy of the original list, like so:
mylist = [1,2,3,4]
mylist.append(list(mylist))
assert mylist == [1,2,3,4,[1,2,3,4]]

It's doing that because you're telling Python to append a list(my_list) to a list. If you want to extend the list with the contents of the list, you can do this:
new_list = old_list + new_list
output: [1, 2, 3, 4, 1, 2, 3, 4]
or you can use the extend method.
old_list.extend(my_list)
Which will modify the old_list in place.

Related

List non-mutating method

Is there in python any method that instead of mutate the original list it returns a new object?
In JavaScript there is at least one:
const originalArray = [1,2,3]
originalArray.concat(4) // returns a new array
In Python, this will return a new list:
originalArray = [1,2,3]
originalArray + [4]
Or if you want to create a new copy of the list use slices:
originalArray[:]
List comprehensions will also create a new list:
[x for x in originalArray]
This is yet another way:
import copy
copy.copy(originalArray)
And there's also the built-in copy() method, as shown in Ronald's answer.
You can simply use the copy method:
list1 = ['a','b','c']
list2 = list1.copy()
list1 is list2, list1 == list2
returns
(False, True)
Showing that you have new object with the same content.

Python Theory About Equal Operator and Array Definition

I stumbled upon a theoretical question about how python works, and it got me puzzled. I tried to understand exactly what happened but couldn't find the answer in google - I'm a beginner, so I don't even know the terminology to make the apropriate search.
On the following code, when calling the function it changes myList, while I only wanted to create a list2 which was a copy of list1 (myList).
myList = [1,2,3,4,5,(1,2),(3,4)]
def onlyTuples(list1):
list2 = list1 # here is my question
for index,e in enumerate(list2):
if type(list2[index]) is not tuple:
list2[index] = (list2[index],)
return(list2)
print(myList)
create_new_list = onlyTuples(myList) # triggered by this call
print(myList)
It's all good if I change list2 = list1 to list2 = list(list1) and myList won't be changed when calling the function, but why?
The same thing doesn't happen with something like this:
a = 6
b = a
b = 7
print(a)
Any light upon the question will be appreciated. Thanks!
In python lists are passed by reference, so when you pass list to a function you pass its address in the memory. list2 = list1 won't create a copy of the list, it will save in list2 the address saved in list1. so change of list2 will change list1, but the function in the class list doesn't save the address, it copy a sequence to a list
To make a copy of a list, use:
newList = myList.copy()

Nested For Loops, Unable to store Iterations without Catch 22

In the beginning I have a master list I intend to put everything in:
master_list = []
I have data stored in nested lists like this:
multi_list = [[1,2,3,4,5],[6,7,8,9,10]]
The end result needs to have this data converted to a list of dicts like this:
master_list
>> [{'x1':1,'x2':2,'y1':3,'y2':4,'id':5},{'x1':6,'x2':7,'y1':8,'y2':9,'id':10}]
So that's my end goal. My approach to reach this goal was as follows:
multi_list = [[1,2,3,4,5],[6,7,8,9,10]]
master_list = []
iterating_dict = {}
for n in multi_list:
for idx,i in enumerate(['x1','x2','y1','y2','id']):
iterating_dict[i] = n[idx]
master_list.append(iterating_dict)
master_list
>>[{'x1':6,'x2':7,'y1':8,'y2':9,'id':10},{'x1':6,'x2':7,'y1':8,'y2':9,'id':10}]
What ends up happening is the second item in multi_list is stored twice. I want it to store converted dicts for all items in multi_list. What I believe this means is the append is not in the right place of the loop. However, when I put it further inside the loop, it appends nothing to master_list. I can't put append further outside without it going out of scope.
What are some conventional approaches to this kind of difficulty in python?
You need to reset iterating dict on each iteration of the external for loop. Otherwise it will keep accumulating values.
Something like this should work:
for n in multi_list:
iterating_dict = {}
for idx,i in enumerate(['x1','x2','y1','y2','id']):
iterating_dict[i] = n[idx]
master_list.append(iterating_dict)
master_list = [{key: l[i] for i, key in enumerate(['x1','x2','y1','y2','id'])} for l in multi_list]
try above code snippet, hope this helps
Concise way to do this in python is to use zip and list comprehension.
multi_list = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
dict_keys = ['x1','x2','y1','y2','id']
master_list = [dict(zip(dict_keys, sublist)) for sublist in multi_list]
zip() combines two sequences together and dict() converts it into a key-value pair. That's what you're doing with each sublist in your multi_list and ['x1','x2','y1','y2','id'].
So here we're making a dictionary out of a combined sequence of ['x1','x2','y1','y2','id'] and sublist for every sublist in the multi_list.

Upon shuffling I get a None object. What is wrong?

I have shuffled the list and assigned it to another variable and when I am trying to print it, it is giving output as None? What is wrong ?
list1 = [1,2,3,4,5,6]
list2 = shuffle(list1)
print list2
The random.shuffle() function is designed to take a list and shuffle its contents. It does not return the shuffled list. The documentation states:
Shuffle the sequence x in place.
As such, if you try to assign the return to a variable you will get None.
You can do the following instead:
list1 = [1,2,3,4,5,6]
shuffle(list1)
print list1
If you wish to preserve your original list order:
list1 = [1,2,3,4,5,6]
list2 = list1[::] # make a copy
shuffle(list2)
print list2
Shuffle() function is not accessible directly, so we need to import shuffle module and then we need to call this function using random static object.
#!/usr/bin/python
import random`
list = [1, 2, 3, 4, 5];
random.shuffle(list)
print "list : ", list

Python: Removing a single element from a nested list

I'm having trouble figuring out how to remove something from within a nested list.
For example, how would I remove 'x' from the below list?
lst = [['x',6,5,4],[4,5,6]]
I tried del lst[0][0], but I get the following result:
TypeError: 'str' object doesn't support item deletion.
I also tried a for loop, but got the same error:
for char in lst:
del char[0]
Use the pop(i) function on the nested list. For example:
lst = [['x',6,5,4],[4,5,6]]
lst[0].pop(0)
print lst #should print [[6, 5, 4], [4, 5, 6]]
Done.
Your code works fine. Are you sure lst is defined as [['x',6,5,4],[4,5,6]]? Because if it is, del lst[0][0] effectively deletes 'x'.
Perhaps you have defined lst as ['x',6,5,4], in which case, you will indeed get the error you are mentioning.
You can also use "pop". E.g.,
list = [['x',6,5,4],[4,5,6]]
list[0].pop(0)
will result in
list = [[6,5,4],[4,5,6]]
See this thread for more: How to remove an element from a list by index in Python?

Categories

Resources