Как разрешить методу list append () возвращать новый список


86

Я хочу сделать что-то вроде этого:

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

К сожалению, добавление списка не возвращает измененный список.

Итак, как я могу разрешить appendвозврат нового списка?

Ответы:


149

Не используйте добавление, а конкатенацию:

yourList = myList + [40]

Это возвращает новый список; myListне пострадает. Если вам нужно, чтобы это тоже myListповлияло на использование .append(), то назначьте yourListотдельно от (копии) myList.


2
что могло бы послужить причиной append()возврата Noneвместо того же списка? Какой принцип дзен это нарушит?
Ciprian Tomoiagă

3
@CiprianTomoiaga: см en.wikipedia.org/wiki/Command%E2%80%93query_separation ; list.appendэто команда, а не запрос.
Мартейн Питерс

2
@CiprianTomoiaga: также см. Это письмо от Python BDFL .
Мартейн Питерс

2
@Dieblitzen: верно, OCaml использует связанные списки и связывает их. Списки Python не являются неизменяемыми, поэтому вы не можете сделать это с ними, и, более того, все остальное может быть изменено . Хотя список OCaml содержит неизменяемые объекты, в Python содержимое неизменяемых объектов, таких как кортежи, по-прежнему может быть изменяемым, поэтому вы не можете совместно использовать содержимое с другими контейнерами при объединении.
Мартейн Питерс

2
@Dieblitzen: вот почему в Python для того, чтобы операция конкатенации была действительной, вы должны создать мелкую копию и заплатить время O (N). Я должен был быть более откровенным, извините.
Мартейн Питерс

22

В python 3 вы можете создать новый список, распаковав старый и добавив новый элемент:

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

когда вы делаете:

myList + [40]

На самом деле у вас есть 3 списка.


1
И это немного быстрее
аэробиомат

6

list.appendявляется встроенным и поэтому не может быть изменен. Но если вы хотите использовать что-то другое append, вы можете попробовать +:

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]

Конечно, недостатком этого является то, что создается новый список, который занимает намного больше времени, чем append

Надеюсь это поможет


Но встроенное можно разделить на подклассы, и тогда все пойдет :)
Марцин Вышински

@MarcinWyszynski: да, но они могут быть изменены только внутри подкласса. Встроенный метод встроенного объекта / класса редко может быть перезаписан, если вообще может быть перезаписан
InspectorG4dget

3
Ради вашего собственного рассудка и рассудка ваших коллег никогда не делайте этого :)
Марчин Вышински

2

Вы можете создать подкласс встроенного типа списка и переопределить метод добавления. Или, что еще лучше, создайте новый, который будет делать то, что вы хотите. Ниже приведен код переопределенного метода добавления.

#!/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()

Надеюсь, это поможет.


2

Попробуйте использовать itertools.chain(myList, [40]). Это вернет генератор как последовательность, а не выделит новый список. По сути, это возвращает все элементы из первой итерации до тех пор, пока она не будет исчерпана, а затем переходит к следующей итерации, пока не будут исчерпаны все итерации.


1

Просто чтобы расширить ответ Storstamp

Вам нужно только выполнить myList.append (40)

Он добавит его в исходный список, теперь вы можете вернуть переменную, содержащую исходный список.

Если вы работаете с очень большими списками, это правильный вариант.


-5

Вам нужно только выполнить myList.append (40)

Он добавит его в исходный список, но не вернет новый список.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.