Blog JSystems - z miłości do programowania

Listy



Listy to struktury danych pozwalające przechowywać zestawy wartości. Posiadają wiele wbudowanych możliwości, jak np. możliwość odwracania, sortowania, szybkiego i łatwego przeszukiwania. Najłatwiej zrozumieć działanie list gdy przyjrzymy się jak działają i co mają do zaoferowania.


 


Tworzenie list


Puste listy możemy zdeklarować na jeden z dwóch sposobów:


lista=[]
lista2=list()


Własności obu list będą takie same. Obie pozostają puste po stworzeniu, posiadają identyczne możliwości. Listę stworzyć możemy również od razu zapełniając ją danymi:


lista3=[1,2,3,"Baba Jaga patrzy!"]


Ciekawostka - w Pythonie listy mogą zawierać elementy dowolnych rodzajów, mogą to być elementy zupełnie różnych typów. Nie ma potrzeby zabawy w polimorfizm etc. W tym miejscu chciałbym pozdrowić programistów niektórych innych popularnych języków programowania ;)


Elementem listy może także być inna lista:


lista4=["nie","toperz",123,lista3]


Taką listę możesz wydrukować jak każdy inny element. Wydruk powyższej listy wyświetla na konsoli:


['nie', 'toperz', 123, [1, 2, 3, 'Baba Jaga patrzy!']]


 


 


Pobieranie wartości z list


Z listami możemy pracować podobnie jak z łańcuchami tekstowymi. Zamiast litery ze wskazanej pozycji otrzymamy jednak element na danej pozycji zawarty. Pamiętaj jednak że w Pythonie liczymy od zera (nie tylko w Pythonie)! Dla listy "lista4" z poprzedniego podrozdziału możemy pobrać i wyświetlić element z drugiej pozycji w ten sposób:


print(lista4[1])


Podobnie jak w łańcuchach możemy podawać numer elementu od końca. Pobranie drugiego od końca elementu:


print(lista4[-2])


Możemy wycinać również zakresy list korzystając z pozycji. Podobnie jak w przypadku łańcuchów tekstowych, pamiętamy o niedomknięciu zbioru z prawej strony. Jeśli więc chcemy z listy:


lista4=["nie","toperz",123,lista3]


pobrać element drugi i trzeci, to robimy to tak:


print(lista4[1:3])


A co jeśli zechcemy pobrać elementy od drugiego do przedostatniego? Możemy to zrobić na co najmniej dwa sposoby. Pierwszy:


print(lista4[1:-1])


i drugi:


print(lista4[1:len(lista4)-1])


W powyższym przykładzie posłużyłem się funkcją len, którą znamy ze sprawdzania długości ciągu tekstowego. W przypadku list sprawdza ona ilość elementów na liście. Sposób korzystania zakresów jest identyczny jak przy łańcuchach. Jeśli więc chcemy pobrać wszystko do pozycji 3 włącznie (czyli do indeksu 2), zrobimy to tak:


print(lista4[:3])


Analogicznie pobranie wszystkich elementów od indeksu numer 2 (czyli od trzeciej włącznie pozycji), zrobimy to tak:


print(lista4[2:])


Wyświetlenie całej zawartości listy w sposób nieco bardziej finezyjny niż "print(lista4)":


print(lista4[:])


 


Iterowanie po listach


Jeśli zechcemy przejść po wszystkich elementach listy i coś z nimi zrobić, np. wydrukować na ekranie (czy zapisać do pliku) istnieje bardzo wygodna metoda:


li = ["siała","baba","mak","ale nałożyli",23,"%","VAT"]
for l in li:
    print(l)


Tą pętlę możesz już kojarzyć z łańcuchów tekstowych. W tym przypadku "l" nie jest kolejnych znakiem z łańcucha, a kolejnym elementem listy. Tak więc pętla obróci się tyle razy ile będzie elementów w liście, a "l" za każdym jej obrotem będzie reprezentowało kolejny jej element. Powyższy kod przejdzie po wszystkich elementach listy i wydrukuje na konsoli wszystkie jej elementy po kolei. Jest też sposób dla osób które preferują mniej czytelny kod i łamanie palców na klawiaturze:


for i in range(len(li)):
    print(li[i])


W tym przypadku "i" będzie po prostu liczbą która rośnie przy każdym obrocie pętli o jeden, aż osiągnie wartość równą długości listy. W funkcji print podaję po prostu kolejne elementy listy wybierając je po indeksie.


 


Sprawdzanie czy element znajduje się na liście


Ponieważ znaleźliśmy już nieco analogii do łańcuchów tekstowych, pewnie nie będzie zaskoczeniem że istnieje specjalna konstrukcja bardzo podobna do tej z łańcuchów (w zasadzie tak naprawdę ta sama) która służy do wymienionego w tytule celu:


poszukiwani=["Michael Scofield","Lincoln Burrows","Theodore Bagwell","Uczciwy polityk"]
if("Andrzej Klusiewicz" in poszukiwani):
    print("pszypau")
else:
    print("nie pszypau")


 


Modyfikowanie zawartości listy


Dodawanie nowych wartości i wstawianie w miejsce istniejących


Poniżej prezentuję kilka przykładów dodawania i podmiany elementów na liście. Przyjrzyj się im i za chwilę je omówimy:


lista=[1,2,3,4,5,6,7]
lista.append(8)
print(lista)
lista.insert(0,"X")
print(lista)
lista[1]="Y"
print(lista


Uruchomienie tego kodu wydrukuje na ekran ekran trzy linie:


[1, 2, 3, 4, 5, 6, 7, 8]


['X', 1, 2, 3, 4, 5, 6, 7, 8]


['X', 'Y', 2, 3, 4, 5, 6, 7, 8]


Funkcja "append" powoduje dodanie elementu na końcu listy. Widzimy to w pierwszej wydrukowanej linii - przybyła jedna cyfra na końcu. Funkcja "insert" podstawia wartość w miejsce wskazanego indeksu (tutaj 0) przesuwając resztę elementów w prawo. Widzimy to w drugiej wydrukowanej linii. Zapis typu "lista[indeks]=wartość" nie rozsuwa listy jak insert, a podmienia element pod wskazanym indeksem.


 


Kasowanie elementów z listy


I tu mamy kilka opcji. Ponownie przyjrzymy się dostępnym wariantom na zasadzie kod + wynik. Najpierw kod:


lista=[1,0,2,0,3,0,4,0,5,0,6,0,7,0,3]
del lista[2]
print(lista)
lista.remove(3)
print(lista)
del lista[0:4]
print(lista)


lista.clear()
print(lista)


Teraz wynik:


[1, 0, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 3]


[1, 0, 0, 0, 4, 0, 5, 0, 6, 0, 7, 0, 3]


[4, 0, 5, 0, 6, 0, 7, 0, 3]


[]


Instrukcja "del lista[2]" powoduje skasowanie elementu o podanym indeksie i zsunięcie listy. Tym sposobem usunęliśmy element zawierający cyfrę "2", co widzimy w pierwszej linii wyniku.


Instrukcja "lista.remove(3)" usunie TYLKO PIERWSZE wystąpienie wartości 3 z listy. Widzimy to w linii drugiej wyniku. Trójka z końca nie została usunięta.


"del lista[0:4]" skasuje elementy o indeksach 0-3, co widzimy w linii trzeciej wyniku. W tym przypadku posługujemy się taką samą składnią zakresów jak w przypadku pobierania elementów z listy.


"lista.clear()" kasuje całą zawartość listy, widzimy efekt jej działania w linii czwartej wyniku.


 


Funkcje wbudowane w listy


Funkcje wbudowane przedstawiam wybiórczo, prezentuję te które uważam za najbardziej użyteczne moim zdaniem. Zainteresowanych pozostałymi funkcjami odsyłam do dokumentacji.


 


Sortowanie i odwracanie list


W przypadku list składających się z elementów prostych - ciągów tekstowych albo liczb (ale nie jednego i drugiego w jednej liście) sortowanie jest bardzo łatwe. Przyjrzyjmy się:


pdk=["Ogórek","Pomidor","Ziemniak","Marchew","Steven Hawking"]
pdk.sort()
print(pdk)


Wynik:


['Marchew', 'Ogórek', 'Pomidor', 'Steven Hawking', 'Ziemniak']


Funkcja "sort" posortowała naszą listę alfabetycznie. Uwaga - działa ona bezpośrednio na liście, nie zwraca osobnej zmodyfikowanej listy. Gdyby na liście znajdowały się liczby, zostałyby one posortowane rosnąco. Gdyby lista składała się z mieszanych typów, dostalibyśmy wyjątek:


TypeError: '<' not supported between instances of 'int' and 'str'


Na potrzeby przykładu dodałem do powyższej listy cyfrę.


Co jednak jeśli zechcemy posortować malejąco? W takim przypadku przyda nam się funkcja wbudowana "reverse":


pdk=["Ogórek","Pomidor","Ziemniak","Marchew"]
pdk.sort()
pdk.reverse()
print(pdk)


I oczywiście wynik:


['Ziemniak', 'Pomidor', 'Ogórek', 'Marchew']


Ten sam efekt możemy uzyskać stosując dodatkowy przełącznik funkcji "sort":


pdk=["Ogórek","Pomidor","Ziemniak","Marchew","Steven Hawking"]
pdk.sort(reverse=True)
print(pdk)


Wynik taki sam jak ostatnio:


['Ziemniak', 'Pomidor', 'Ogórek', 'Marchew']


Wiemy już że listy mogą składać się z elementów różnych typów, w tym typów złożonych. Każdy z elementów listy sam również może być listą. Rozważmy taki przykład w kontekście sortowania:


furki=[[3,"Renault"],[2,"Citroen"],[1,"Audi"],[4,"Zaporożec"]]
furki.sort()
print(furki)


Sortowanie w takim wypadku zadziała, pewnie nawet można się domyślić że posortuje po pierwszej wartości z każdej z list:


[[1, 'Audi'], [2, 'Citroen'], [3, 'Renault'], [4, 'Zaporożec']]


A co jeśli zechcielibyśmy posortować alfabetycznie po markach? Także istnieje taka możliwość. Musimy jednak skorzystać z dodatkowej funkcji "itemgetter" znajdującej się w paczce "operator". Musimy tę funkcję zaimportować, zanim zaczniemy z niej korzystać.


from operator import itemgetter
furki=[[3,"Renault"],[2,"Citroen"],[1,"Audi"],[4,"Zaporożec"]]
furki.sort(key=itemgetter(1))
print(furki)


Wynik:


[[1, 'Audi'], [2, 'Citroen'], [3, 'Renault'], [4, 'Zaporożec']]


Zwróć uwagę na trzecią linię kodu. Zastosowałem dodatkowy parametr funkcji sort - "key" łącząc go z wywołaniem funkcji "itemgetter". W funkcji "itemgetter" jako parametr podałem indeks elementu podlisty, po którym ma być posortowana zewnętrzna lista.


 


Inne ciekawe funkcje i możliwości


Zaczniemy od sprawdzania długości listy, oraz ilości wystąpień określonego elementu w liście. Jeśli chcemy sprawdzić ilość elementów w liście, wystarczy posłużyć się znaną nam już i używaną dotąd kilkukrotnie uniwersalną funkcją "len". Gdy zechcemy sprawdzić ile razy występuje jakiś element w liście, posługujemy się funkcją "count":


lista=[1,3,5,8,13,21,34,55,1,1,1,"Batman"]
print(len(lista))
print(lista.count(1))


Z listy możemy też kopiować dane. Poniżej pokazuję dwa sposoby. Albo posługując się zakresami (linia druga), albo stosując funkcję "copy" kopiującą całą listę (czwarta linia). Możnaby zapytać czemu nie zrobić po prostu "kopia=lista"? Takie przypisanie odbywa się przez wskaźnik a nie przez kopię i spowodowałoby, że kopia byłaby w rzeczywistości tą samą listą. Modyfikacje na kopii powodowałyby również modyfikacje na oryginalnej liście.


lista=[1,3,5,8,13,21,34,55,1,1,1,"Batman"]
podlista=lista[2:7]
print(podlista)
kopia=lista.copy()
print(kopia)


Wynik:


[5, 8, 13, 21, 34]


[1, 3, 5, 8, 13, 21, 34, 55, 1, 1, 1, 'Batman']


W odniesieniu do list możemy też stosować funkcje agregujące:


fib=[1,3,5,8,13,21,34,55]
print( sum(fib) , max(fib), min(fib) )


Warunkiem jest jednak to by wszystkie elementy listy były liczbami. Wynik:


140 55 1


Nieco enigmatyczny może wydawać się zapis:


print( sum(fib) , max(fib), min(fib) )


Dotychczas funkcja "print" przyjmowała tylko jeden argument, a tu nagle trzy (?)... Nadal przyjmuje jeden argument, z tym że argumentem tym jest krotka :) Jest to specjalny złożony typ danych, którym zajmiemy się w kolejnym podrozdziale.


Z innych ciekawych elementów przedstawię jeszcze funkcję "index". Jest to metoda sprawdzająca pod jakim indeksem na liście znajduje się wskazany element:


fib=[1,3,5,8,13,21,34,55]
print(     fib.index(13)    )


Gdyśmy jako argument podali element którego na liście nie ma, otrzymalibysmy wyjątek:


ValueError: 14 is not in list


 

Przyjdź do nas na szkolenie z języka Python! Mamy szereg szkoleń w ofercie, od podstawowych po aplikacje webowe z użyciem Django, analizę danych, tesowanie, machine learning i wiele innych.
Sprawdź dostępne szkolenia Python
Zapisz się do newslettera aby otrzymywać najnowsze świeżynki pojawiające się na blogu!