148

I want to do something like this:

myList = [10, 20, 30]
yourList = myList.append(40)

Unfortunately, list append does not return the modified list.

So, how can I allow append to return the new list?


See also: Why do these list operations (methods) return None, rather than the resulting list?

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Wilk
  • 7,873
  • 9
  • 46
  • 70

8 Answers8

239

Don't use append but concatenation instead:

yourList = myList + [40]

This returns a new list; myList will not be affected. If you need to have myList affected as well either use .append() anyway, then assign yourList separately from (a copy of) myList.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 4
    what would have been the rationale behind `append()` returning `None` instead of the same list ? Which zen principle would it violate ? – Ciprian Tomoiagă May 12 '17 at 18:54
  • 4
    @CiprianTomoiaga: see https://en.wikipedia.org/wiki/Command%E2%80%93query_separation; `list.append` is a command, not a query. – Martijn Pieters May 12 '17 at 19:11
  • 2
    @CiprianTomoiaga: also see [this email from the Python BDFL](https://mail.python.org/pipermail/python-dev/2003-October/038855.html). – Martijn Pieters May 12 '17 at 19:13
  • The issue with using + for appending just one element is it is O(n) in time complexity. Is there an equivalent of the Cons operator (as in some functional languages) that is just O(1), but returns the new list as well? – Dieblitzen Dec 16 '18 at 03:03
  • @Dieblitzen: you can't have a O(1) copy operation of a sized data structure. So no, there is no equivalent, `cons` operators always take O(n) time. – Martijn Pieters Dec 17 '18 at 10:18
  • The cons operator is not O(n) (at least in OCaml) because the list is immutable. I have linked a resource on this below. I am asking if it is possible in python to use an operator similar to the cons operator in functionality, but I guess not, since python lists are mutable. http://www.cs.cornell.edu/courses/cs3110/2018fa/textbook/data/mutating_lists.html – Dieblitzen Dec 21 '18 at 05:21
  • 2
    @Dieblitzen: right, so OCaml uses linked lists and connects those. Python lists are not immutable so you can't do that with those, and moreover, *everything else can be mutable*. While an OCaml list contains immutable objects, in Python the contents of immutable objects such as tuples can still be mutable, so you can't share the contents with other containers when concatenating. – Martijn Pieters Dec 21 '18 at 11:49
  • 2
    @Dieblitzen: which is why in Python, for a concatenation operation to be valid, you must create a shallow copy, and pay the O(N) time. I should have been more explicit, sorry. – Martijn Pieters Dec 21 '18 at 11:49
  • So @MartijnPieters, the concatenation operator `+` here would be a query? – flow2k Dec 06 '19 at 23:01
  • 1
    @flow2k yes because it doesn’t alter the operands; instead it produces a new object. – Martijn Pieters Dec 07 '19 at 23:50
  • @MartijnPieters I remembered the functional in-place operators, like `operator.iadd(.)`. So this type of functions violates CQS? – flow2k Dec 09 '19 at 02:44
  • And for sets, `yourSet = yourSet | {40}` – Ryan Dec 04 '21 at 22:32
59

In python 3 you may create new list by unpacking old one and adding new element:

a = [1,2,3]
b = [*a,4] # b = [1,2,3,4] 

when you do:

myList + [40]

You actually have 3 lists.

vaer-k
  • 10,923
  • 11
  • 42
  • 59
8

Unfortunately, none of the answers here solve exactly what was asked. Here is a simple approach:

lst = [1, 2, 3]
lst.append(4) or lst  # the returned value here would be the OP's `yourList`
# [1, 2, 3, 4]

One may ask the real need of doing this, like when someone needs to improve RAM usage, do micro-benchmarks etc. that are, usually, useless. However, sometimes someone is really "asking what was asked" (I don't know if this is the case here) and the reality is more diverse than we can know of. So here is a (contrived because out-of-a-context) usage... Instead of doing this:

dic = {"a": [1], "b": [2], "c": [3]}

key, val = "d", 4  # <- example
if key in dic:
    dic[key].append(val)
else:
    dic[key] = [val]
dic
#  {'a': [1], 'b': [2], 'c': [3], 'd': [4]}

key, val = "b", 5  # <- example
if key in dic:
    dic[key].append(val)
else:
    dic[key] = [val]
dic
#  {'a': [1], 'b': [2, 5], 'c': [3], 'd': [4]}

One can use the OR expression above in any place an expression is needed (instead of a statement):

key, val = "d", 4  # <- example
dic[key] = dic[key].append(val) or dic[key] if key in dic else [val]
#  {'a': [1], 'b': [2], 'c': [3], 'd': [4]}

key, val = "b", 5  # <- example
dic[key] = dic[key].append(val) or dic[key] if key in dic else [val]
#  {'a': [1], 'b': [2, 5], 'c': [3], 'd': [4]}

Or, equivalently, when there are no falsy values in the lists, one can try dic.get(key, <default value>) in some better way.

dawid
  • 663
  • 6
  • 12
7

list.append is a built-in and therefore cannot be changed. But if you're willing to use something other than append, you could try +:

In [106]: myList = [10,20,30]

In [107]: yourList = myList + [40]

In [108]: print myList
[10, 20, 30]

In [109]: print yourList
[10, 20, 30, 40]

Of course, the downside to this is that a new list is created which takes a lot more time than append

Hope this helps

inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241
4

Try using itertools.chain(myList, [40]). That will return a generator as a sequence, rather than allocating a new list. Essentially, that returns all of the elements from the first iterable until it is exhausted, then proceeds to the next iterable, until all of the iterables are exhausted.

jsears
  • 4,511
  • 2
  • 31
  • 36
2

Just to expand on Storstamp's answer

You only need to do myList.append(40)

It will append it to the original list,now you can return the variable containing the original list.

If you are working with very large lists this is the way to go.

1

You can subclass the built-in list type and redefine the 'append' method. Or even better, create a new one which will do what you want it to do. Below is the code for a redefined 'append' method.

#!/usr/bin/env python

class MyList(list):

  def append(self, element):
    return MyList(self + [element])


def main():
  l = MyList()
  l1 = l.append(1)
  l2 = l1.append(2)
  l3 = l2.append(3)
  print "Original list: %s, type %s" % (l, l.__class__.__name__)
  print "List 1: %s, type %s" % (l1, l1.__class__.__name__)
  print "List 2: %s, type %s" % (l2, l2.__class__.__name__)
  print "List 3: %s, type %s" % (l3, l3.__class__.__name__)


if __name__ == '__main__':
  main()

Hope that helps.

Marcin Wyszynski
  • 2,188
  • 1
  • 17
  • 16
-5

You only need to do myList.append(40)

It will append it to the original list, not return a new list.

Storstamp
  • 425
  • 2
  • 8