python list appending is not working [duplicate] - python

This question already has answers here:
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.
I have something similar to:
>>> S=list()
>>> T=[1,2,3]
>>> for t in T:
... print(S.append(t))
The output I am getting is:
...
None
None
None
I expect S contains t. Why this is not working with me ?

list.append() does not return anything. Because it does not return anything, it default to None (that is why when you try print the values, you get None).
It simply appends the item to the given list in place. Observe:
>>> S = list()
>>> T = [1,2,3]
>>> for t in T:
... S.append(t)
>>> print(S)
[1, 2, 3]
Another example:
>>> A = []
>>> for i in [1, 2, 3]:
... A.append(i) # Append the value to a list
... print(A) # Printing the list after appending an item to it
...
[1]
[1, 2]
[1, 2, 3]

. append() is a list method, that does not return a value it alters the list. For example .index() or .count() methods return object values, while .append() alters the object. For example:
T = [1, 2, 3]
T.append(4)
print(T)
Result:
[1, 2, 3, 4]
We can use .append() to change the list S and add elements from the list T. Lists S, and T are two separate objects with two different addresses in the memory. With the function id() you can check that.
T = [1, 2, 3]
print(id(T))
S = list()
print(S)
print(id(S))
for t in T:
S.append(t)
print(S)
print(id(S))
Result:
2476978999688
[]
2476978081224
[1, 2, 3]
2476978081224
If you want to use only two different names (S and T) for the same list, we can write:
print(T)
print(id(T))
S = T
print(S)
print(id(S))
Result:
[1, 2, 3]
2476978999688
[1, 2, 3]
2476978999688

Related

Appending to a list comprehension in Python returns None

This is a question out of curiosity rather than trying to use it for a practical purpose.
Consider I have the following simple example where I generate a list through list comprehension:
>>> a = [1, 2, 3]
>>> b = [2 * i for i in a]
>>> b
[2, 4, 6]
>>> b.append(a)
>>> b
[2, 4, 6, [1, 2, 3]]
However if I try and do this all in one action
>>> a = [1, 2, 3]
>>> b = [2 * i for i in a].append(a)
>>> b == None
True
The result returns None. Is there any reason why this is the case?
I would have thought that an action like this would either return an answer like in the first example or throw an error.
For reference I'm using Python 3.6.5
append only works on variables, not list literals, since it updates the list object itself and does not return the resulting list.
As #Tomalak mentioned noted, running a similar operation on a simple list also returns None
>>> [1, 2, 3].append(4) == None
True
You can use concatination + instead of append in list comprehension
In [1]: a = [1, 2, 3]
In [2]: b = [2 * i for i in a] + [a]
In [3]: b
Out[3]: [2, 4, 6, [1, 2, 3]]
#ScottMcC, methods defined on mutable objects like list, dictionary mostly perform operations on calling object and doesn't return anything.
In case of immutable object like string you may see, methods return the modified form(a different object) of the calling object. In case of list, it's different.
You can't expect the below operations on list kind of mutable objects.
s = "hello DJANGO"
s2 = s.upper()
s3 = s.lower()
print(s) # hello DJANGO
print(s2) # HELLO DJANGO
print(s3) # hello django
Now, have a look at the below examples.
list is mutable object.
Calling sort() method on list directly modified the calling object and doesn't return anything (That's why None).
Calling sorted() function doesn't alter the passing list. It creates a separate sorted list based on the passed list. As it is not a method defined on list object, it returns the new sorted list.
append() method appends item on the calling list and doesn't return anything. Once you call it, you are done with updating (appending an item) the list.
# sort() method defined on list updates the calling list
# As it updates current list, it doesn't return anything. That's why None.
a = [5, 8, 1, 2, 7]
n = a.sort()
print (a)
print(n)
print ()
# sorted() function returns a new sorted list
# It doesn't update the calling list a2
a2 = [5, 8, 1, 2, 7];
n = sorted(a2);
print (a2)
print(n)
print()
# append() is method defined on list, it updates calling list so it doesn't return anything (None)
l = []
n = l.append(34)
print(l)
print (n)
Output
[1, 2, 5, 7, 8]
None
[5, 8, 1, 2, 7]
[1, 2, 5, 7, 8]
[34]
None

Remove and return adjacent elements from a list [duplicate]

This question already has answers here:
Remove adjacent element in a list in python
(2 answers)
Closed 7 years ago.
I have a list like this: [1, 3, 4, 5, 1]
and I want to remove the first n elements, so for n = 3, I want to return that list, while removing it from the original list. So I'd have [1,3,4]
and my original list is now [5, 1].
What is the best way to do that in python?
In Python 2.7 this would look like the following. Simply extract a partial list and delete the unneeded part in the original version.
lst = [1, 3, 4, 5, 1]
new_lst = lst[:3]
del lst[:3]
print lst
print new_lst
If you want to mutate the original object, you can change it using [:]. For example:
>>> x = ['a','b','c','d','e']
>>> x[:], removed = x[3:], x[:3]
>>> x
['d', 'e']
>>> removed
['a', 'b', 'c']
This works because the terms on the right hand side, x[3:] and x[:3], are both evaluated before they're assigned to the targets on the left (x[:] and removed).
Something like this?
def pop_n(lst, n):
"""
Deletes the first *n* elements from *lst* and returns them.
"""
# validate inputs
# might want to use something other than isinstance()
if not isinstance(n, int) or n < 0:
raise ValueError("n must be a non-negative integer, not {}"
.format(n))
# store the elements to return
ret = lst[:n]
# remove the elements from the original list
del lst[:n]
return ret
EDIT: Here's a demonstration with your example case.
>>> x = [1, 3, 4, 5, 1]
>>> pop_n(x, 3)
[1, 3, 4]
>>> x
[5, 1]
>>> original = [1, 3, 4, 5, 1]
>>> removed, original[:3] = original[:3], ()
>>> removed, original
([1, 3, 4], [5, 1])

Lists and Function Arguments

>>> def duplicate(l):
... l = l + l
...
>>> l1 = [1, 2, 3]
>>> duplicate(l1)
>>> l1
[1, 2, 3]
I believe the function above duplicates the list. But why is the result not [1, 2, 3, 1, 2, 3]?
Concatenation of two list objects (as you do with l + l) always creates a new list object. In your function you then assign that new list object back to the local variable l, which is independent of the global reference l1. The original list object is not affected because only the contents of the list were copied.
If you wanted to alter the list object in place, you need to extend l with itself:
def duplicate(l):
l.extend(l)
list.extend() copies all elements from the list you pass in and adds them to the end of the list object you called it on. Passing in the list itself is safe; it'll only copy the original elements.
Demo:
>>> def duplicate(l):
... l.extend(l)
...
>>> l1 = [1, 2, 3]
>>> duplicate(l1)
>>> l1
[1, 2, 3, 1, 2, 3]

Reversing order of a tuple of list

I have a tuple ([1,2,3], [4,5,6]) and I want to reverse the list inside so that it becomes ([3,2,1],[6,5,4]) without having to create a new tuple and adding elements to it. The closest I've gotten is:
my_func(....):
for i in tuple(...):
i = i[::-1]
return tuple(....)
problem is that while i prints out what I want..the tuple was never changed
Tuples are immutable but the objects contained by them can be either mutable or immutable, so if we modify a mutable object contained by the tuple then the change will be reflected at all the references of that object, that includes the tuple as well.
As in this case we've lists, so, all we need to do is to loop over the tuple and call .reverse() on the lists.
>>> t = ([1,2,3], [4,5,6])
>>> for x in t:
... x.reverse()
...
>>> t
([3, 2, 1], [6, 5, 4])
Another example:
>>> x = [1, 2, 3]
>>> t = (x, 'abc')
>>> x.reverse()
>>> t
([3, 2, 1], 'abc')
>>> x
[3, 2, 1]
As frostnational says, tuples are immutable, so you will have to create new ones.
You could do something like this:
>>> a = ([1,2,3],[4,5,6])
>>> b = map(lambda t: reversed(t), a)
>>> for sublist in b:
... for item in sublist:
... print(item)
...
3
2
1
6
5
4

python list comprehension and extend() [duplicate]

This question already has answers here:
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.
Working my way into Python (2.7.1)
But failing to make sense (for hours) of this:
>>> a = [1, 2]
>>> b = [3, 4]
>>>
>>> a.extend([b[0]])
>>> a
[1, 2, 3]
>>>
>>> a.extend([b[1]])
>>> a
[1, 2, 3, 4]
>>>
>>> m = [a.extend([b[i]]) for i in range(len(b))] # list of lists
>>> m
[None, None]
The first two extends work as expected, but when compacting the same in a list comprehension it fails.
What am i doing wrong?
extend modifies the list in-place.
>>> [a + b[0:i] for i in range(len(b)+1)]
[[1, 2], [1, 2, 3], [1, 2, 3, 4]]
list.extend() extends a list in place. Python standard library methods that alter objects in-place always return None (the default); your list comprehension executed a.extend() twice and thus the resulting list consists of two None return values.
Your a.extend() calls otherwise worked just fine; if you were to print a it would show:
[1, 2, 3, 4, 3, 4]
You don't see the None return value in the Python interpreter, because the interpreter never echoes None results. You could test for that explicitly:
>>> a = []
>>> a.extend(['foo', 'bar']) is None
True
>>> a
['foo', 'bar']
the return value of extend is None.
extend function extends the list with the value you've provided in-place and returns None. That's why you have two None values in your list. I propose you rewrite your comprehension like so:
a = [1, 2]
b = [3, 4]
m = [a + [v] for v in b] # m is [[1,2,3],[1,2,4]]
For python lists, methods that change the list work in place and return None. This applies to extendas well as to append, remove, insert, ...
In reply to an older question, I sketched an subclass of list that would behave as you expected list to work.
Why does [].append() not work in python?
This is intended as educational. For pros and cons.. look at the comments to my answer.
I like this for the ability of chaining methods and working in a fluent style, e.g. then something like
li = FluentList()
li.extend([1,4,6]).remove(4).append(7).insert(1,10).reverse().sort(key=lambda x:x%2)
would be possible.
a.extend() returns None.
You probably want one of these:
>>> m = a + b
>>> m
[1, 2, 3, 4]
>>> a.extend(b)
>>> a
[1, 2, 3, 4]
Aside from that, if you want to iterate over all elements of a list, you just can do it like that:
m = [somefunction(element) for element in somelist]
or
for element in somelist:
do_some_thing(element)
In most cases there is no need to go over the indices.
And if you want to add just one element to a list, you should use somelist.append(element) instead of `somelist.extend([element])

Categories