Kurs Python · Moduł 2: Struktury danych
Metody list - narzędzia eksploracyjne
W tej lekcji8
Witaj! Wyobraź sobie poranek w obozie bazowym. Pierwszy tropiciel wraca z wieścią o nowym gatunku, drugi prosi, żeby jego obserwację wpisać na sam początek, a trzeci przyznaje, że jedną zebrę zanotował dwa razy. Twój dziennik obserwacji to lista i musi nadążyć za tymi zmianami. Można by za każdym razem budować nową listę od zera, ale to jak przepisywanie całego dziennika, żeby dopisać jedną linijkę.
Lista ma do tego wbudowane narzędzia, czyli metody. Metoda to funkcja przypięta do konkretnego obiektu, którą wywołujesz po kropce, na przykład sightings.append("Lew"). Kropka mówi Pythonowi: sięgnij do plecaka tej listy i użyj narzędzia o tej nazwie.
Dodawanie na koniec - append()
Najczęstsza sytuacja na szlaku: nowe odkrycie trafia na koniec dziennika. Do tego służy metoda append(), która przyjmuje jeden element i dokleja go za ostatnim wpisem.
1sightings = ["Tygrys", "Słoń"]
2sightings.append("Pyton")
3print(sightings) # ['Tygrys', 'Słoń', 'Pyton']Nie ma tu przypisania ze znakiem =: lista zmieniła się na miejscu, a wcześniejsze wpisy zachowały kolejność. To właśnie znaczy, że lista jest mutowalna.
Pułapka: append() nic nie zwraca
Skoro metoda zmienia listę na miejscu, nie oddaje nowej listy. Zwraca None, czyli znany z pierwszego modułu "brak wartości". Zobacz, co się stanie, gdy ktoś spróbuje zapisać jej wynik:
1sightings = ["Tygrys", "Słoń"]
2result = sightings.append("Lew")
3print(result) # None
4print(sightings) # ['Tygrys', 'Słoń', 'Lew']Lew trafił do listy, ale w result nie ma nic. Gdyby ktoś napisał sightings = sightings.append("Lew"), zmienna straciłaby cały dziennik i wskazywałaby na None. Ta sama zasada dotyczy insert(), extend(), remove() i sort(): zmieniają listę i zwracają None.
Wstawianie w środek - insert()
Czasem liczy się miejsce. Planujesz trasę i okazuje się, że między obozem a wodospadem płynie rzeka. Metoda insert() przyjmuje dwa argumenty: indeks, pod którym ma stanąć nowy element, oraz sam element.
1route = ["Obóz", "Wodospad", "Meta"]
2route.insert(1, "Rzeka")
3print(route) # ['Obóz', 'Rzeka', 'Wodospad', 'Meta']Rzeka stanęła pod indeksem 1, a wodospad i meta przesunęły się o jedno miejsce w prawo. Nic nie zniknęło ani nie zostało nadpisane. Wywołanie route.insert(0, "Start") postawiłoby nowy punkt na samym początku trasy.
Wiele elementów naraz - extend()
Do obozu dociera drugi zespół i chcesz dopisać wszystkich jego członków. Kusi, żeby użyć append(), ale ta metoda zawsze dodaje dokładnie jeden element, nawet jeśli tym elementem jest cała lista. Porównaj obie metody:
1team = ["Darwin", "Ala"]
2team.extend(["Maja", "Tomek"])
3print(team) # ['Darwin', 'Ala', 'Maja', 'Tomek']
4team.append(["Ola", "Kuba"])
5print(team) # ['Darwin', 'Ala', 'Maja', 'Tomek', ['Ola', 'Kuba']]Metoda extend() dopisała każdą osobę osobno, a append() wstawiła całą listę jako jeden element, więc na końcu zespołu pojawiła się lista w liście. Moja rada: gdy dołączasz kilka elementów naraz, sięgaj po extend().
A co z operatorem +?
Listy można też łączyć operatorem +, ale on działa inaczej niż metody. Nie zmienia żadnej z list, tylko buduje zupełnie nową:
1base = ["Tygrys"]
2bigger = base + ["Lew"]
3print(base) # ['Tygrys']
4print(bigger) # ['Tygrys', 'Lew']Lista base została nietknięta. Zapamiętaj ten podział: metody takie jak append() zmieniają listę na miejscu, a operator + i slicing, na przykład base[::-1], tworzą nową listę.
Usuwanie po wartości - remove()
Tropiciel, który zanotował zebrę dwa razy, prosi o poprawkę. Znasz nazwę, ale nie pozycję, więc używasz metody remove(), która przeszukuje listę od lewej i usuwa pierwsze trafienie.
1animals = ["Zebra", "Lew", "Zebra", "Pyton"]
2animals.remove("Zebra")
3print(animals) # ['Lew', 'Zebra', 'Pyton']Zniknęła tylko pierwsza zebra, druga wciąż jest na liście. Jeśli wartości w ogóle nie ma, Python zgłasza błąd ValueError. Dlatego przy niepewnych danych najpierw sprawdź obecność operatorem in:
1if "Hiena" in animals:
2 animals.remove("Hiena")
3print(animals) # ['Lew', 'Zebra', 'Pyton']Hieny nie było, więc warunek nie dopuścił do wywołania remove(), a lista pozostała bez zmian.
Usuwanie po pozycji - pop()
Wieczorem wyjmujesz z plecaka ostatnią spakowaną rzecz, żeby od razu jej użyć. Tu przydaje się pop(), jedyna z poznanych metod usuwających, która oddaje usunięty element.
1supplies = ["Namiot", "Mapa", "Kompas"]
2last_item = supplies.pop()
3print(last_item) # Kompas
4print(supplies) # ['Namiot', 'Mapa']Bez argumentu pop() zabiera i zwraca ostatni element, a z indeksem, na przykład supplies.pop(0), wskazaną pozycję. Kiedy co wybrać? Jeśli znasz nazwę, użyj remove(). Jeśli znasz pozycję albo potrzebujesz usuniętego elementu, użyj pop().
Szukanie i liczenie - index() i count()
Nie każde narzędzie zmienia listę. Dwie metody tylko czytają dziennik: index() podaje pozycję pierwszego wystąpienia, a count() liczy wszystkie wystąpienia.
1sightings = ["Zebra", "Lew", "Zebra", "Słoń", "Zebra"]
2print(sightings.index("Lew")) # 1
3print(sightings.count("Zebra")) # 3Po tych wywołaniach lista wygląda dokładnie tak samo. Uważaj na różnicę przy brakującym elemencie: index() zgłosi ValueError, a count() spokojnie zwróci 0.
Sortowanie - sort() i sorted()
Na koniec dnia chcesz uporządkować wagi zwierząt od najlżejszego. Metoda sort() robi to na miejscu:
1weights = [190, 5000, 3, 350]
2weights.sort()
3print(weights) # [3, 190, 350, 5000]Lista jest teraz posortowana rosnąco, a pierwotna kolejność przepadła. Tak jak append(), metoda sort() zwraca None, więc nie przypisuj jej wyniku do zmiennej.
Jeśli pierwotna kolejność jest ważna, bo zapisuje historię obserwacji, użyj funkcji sorted(). To nie metoda, tylko wbudowana funkcja, więc listę podajesz w nawiasach, a nie przed kropką. Parametr reverse=True odwraca kierunek sortowania.
1weights = [190, 5000, 3, 350]
2ranking = sorted(weights, reverse=True)
3print(ranking) # [5000, 350, 190, 3]
4print(weights) # [190, 5000, 3, 350]Funkcja sorted() zwróciła nową listę od największej wagi, a lista weights zachowała kolejność z dziennika. Parametr reverse=True działa też w metodzie: weights.sort(reverse=True). Polecam prostą zasadę: gdy stara kolejność nie będzie Ci potrzebna, wybierz sort(), a gdy chcesz ją zachować, wybierz sorted().
Wszystko razem
Na koniec krótka sekwencja, w której jedna lista przechodzi po kolei przez kilka narzędzi:
1numbers = [3, 1, 4]
2numbers.append(2)
3numbers.sort()
4print(numbers) # [1, 2, 3, 4]Dwójka trafiła na koniec, a potem metoda sort() ułożyła liczby rosnąco. Obie metody zmieniły tę samą listę i ani razu nie przypisaliśmy ich wyniku do zmiennej.
Pamiętaj: metody, które zmieniają listę, robią to na miejscu i poza pop() zwracają None, a gdy chcesz zachować oryginał, sięgnij po sorted() albo operator +. W następnej lekcji Darwin pokaże Ci słowniki, czyli katalog, w którym każde odkrycie dostaje własną kartę.
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Co robi metoda append() na liście?
2. Co zwraca metoda pop()?
3. Jaka jest różnica między sort() a sorted()?
4. Co robi: lista.insert(0, 'X')?
Zadania praktyczne w grze
- Układanie w poziomie
Ułóż wywołanie, które dopisze do listy team wszystkie osoby z listy new_members:
- Edytor kodu
Dodaj 'Pyton' do listy animals = ['Tygrys', 'Słoń']
- Edytor kodu
Usuń ostatni element z listy species = ['Tygrys', 'Słoń', 'Papuga'] i wypisz go
- Edytor kodu
Posortuj listę numbers = [5, 2, 8, 1, 9] rosnąco
- Klikanie w kolejności
Kliknij w kolejności: animals.append('Pyton')
- Klikanie w kolejności
Kliknij w kolejności: sorted(numbers, reverse=True)
- Układanie w pionie
Uporządkuj kroki: stwórz listę, dodaj element, posortuj, wypisz: