Jak zezwolić metodzie append () na zwrócenie nowej listy

85

Chcę zrobić coś takiego:

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

Niestety dołączenie listy nie zwraca zmodyfikowanej listy.

Jak więc mogę zezwolić appendna zwrócenie nowej listy?

Wilk
źródło

Odpowiedzi:

148

Nie używaj zamiast tego dołączania, ale konkatenacji:

yourList = myList + [40]

To zwraca nową listę; myListnie ulegnie zmianie. Jeśli musisz mieć myListwpływ także użyć .append()w każdym razie, a następnie przypisać yourListoddzielnie (kopia) myList.

Martijn Pieters
źródło
2
jakie byłoby uzasadnienie append()powrotu Nonezamiast tej samej listy? Którą zasadę zen by to naruszyło?
Ciprian Tomoiagă
3
@CiprianTomoiaga: patrz en.wikipedia.org/wiki/Command%E2%80%93query_separation ; list.appendjest poleceniem, a nie zapytaniem.
Martijn Pieters
2
@CiprianTomoiaga: zobacz również tę wiadomość e-mail z Python BDFL .
Martijn Pieters
2
@Dieblitzen: racja, więc OCaml używa połączonych list i je łączy. Listy Pythona nie są niezmienne, więc nie możesz tego zrobić z nimi, a ponadto wszystko inne może być zmienne . Chociaż lista OCaml zawiera niezmienne obiekty, w Pythonie zawartość niezmiennych obiektów, takich jak krotki, może być nadal zmienna, więc nie można udostępniać zawartości innym kontenerom podczas łączenia.
Martijn Pieters
2
@Dieblitzen: dlatego w Pythonie, aby operacja konkatenacji była prawidłowa, musisz utworzyć płytką kopię i zapłacić czas O (N). Powinienem był być bardziej dosadny, przepraszam.
Martijn Pieters
22

W Pythonie 3 możesz stworzyć nową listę, rozpakowując starą i dodając nowy element:

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

kiedy robisz:

myList + [40]

W rzeczywistości masz 3 listy.

Damian Paszkowski
źródło
1
I jest trochę szybciej
aerobiomat
6

list.appendjest wbudowany i dlatego nie można go zmienić. Ale jeśli chcesz użyć czegoś innego niż append, możesz spróbować +:

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]

Oczywiście wadą jest to, że tworzona jest nowa lista, która zajmuje dużo więcej czasu niż append

Mam nadzieję że to pomoże

inspectorG4dget
źródło
Ale wbudowaną można podklasę i wszystko idzie :)
Marcin Wyszynski
@MarcinWyszynski: tak, ale można je modyfikować tylko w ramach podklasy. Wbudowana metoda wbudowanego obiektu / klasy rzadko może zostać nadpisana, jeśli w ogóle
inspectorG4dget
3
Dla własnego zdrowia psychicznego i dla zdrowia swoich współpracowników nigdy nie powinieneś tego robić :)
Marcin Wyszynski
2

Możesz podklasować wbudowany typ listy i przedefiniować metodę „dołączania”. Lub jeszcze lepiej, stwórz nowy, który zrobi to, co chcesz. Poniżej znajduje się kod przedefiniowanej metody „append”.

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

Mam nadzieję, że to pomoże.

Marcin Wyszyński
źródło
2

Spróbuj użyć itertools.chain(myList, [40]). To zwróci generator jako sekwencję zamiast alokacji nowej listy. Zasadniczo zwraca to wszystkie elementy od pierwszej iteracji do jej wyczerpania, a następnie przechodzi do następnej iteracji, aż wszystkie iterowalne zostaną wyczerpane.

jsears
źródło
1

Aby rozwinąć odpowiedź Storstampa

Musisz tylko zrobić myList.append (40)

Doda go do oryginalnej listy, teraz możesz zwrócić zmienną zawierającą oryginalną listę.

Jeśli pracujesz z bardzo dużymi listami, to jest właściwy sposób.

ajayinvictus10
źródło
-5

Musisz tylko zrobić myList.append (40)

Doda go do oryginalnej listy, a nie zwróci nowej listy.

Stempel
źródło