Python - wprowadzenie

09 - Podstawowe kolekcje cz. I - listy i krotki

Kolekcje, jak wskazuje nazwa, pozwalają przechowywać razem wiele elementów. Należą one do struktur danych. Python, zwłaszcza uwzględniając dodatkowe biblioteki, oferuje wiele struktur danych, na razie przyjrzymy się tym podstawowym.

Listy (ang. lists) i krotki (ang. tuples) służą do przechowywania wielu elementów w określonej kolejności. Podstawowa różnica między nimi jest taka, że listy są modyfikowalne a krotki nie. Zacznijmy od list, pewnie częściej będziesz ich używać.

Listy

Utwórzmy pierwsze listy:

zasady_azotowe = ['adenina', 'guanina', 'cytozyna', 'tymina', 'uracyl']
print(zasady_azotowe)
['adenina', 'guanina', 'cytozyna', 'tymina', 'uracyl']
pierwsze_liczby_pierwsze = [2, 3, 5, 7, 11, 13]
print(pierwsze_liczby_pierwsze)
[2, 3, 5, 7, 11, 13]
roznosci = ['AGA', 23, 3.14, True]
print(roznosci)
['AGA', 23, 3.14, True]

Jak widać, na powyższych przykładach, elementy listy przedzielone są przecinkami i umieszcza się je w parze nawiasów kwadratowych []. Mogą one być tego samego typu, ale nie muszą.

Sprawdźmy typ:

print(type(roznosci))
<class 'list'>

Możemy też utworzyć pustą listę używając nawiasów kwadratowych, lub funkcji list():

nowa_lista_1 = []
print(nowa_lista_1)
print(type(nowa_lista_1))
nowa_lista_2 = list()
print(nowa_lista_2)
print(type(nowa_lista_2))
[]
<class 'list'>
[]
<class 'list'>

Później możemy do niej dodać elementy, korzystając ze sposobów pokazanych w dalszej części tej lekcji.

Uzyskiwanie elementów listy

Skoro wiemy już jak stworzyć listę elementów, warto by poznać sposób na ,,wyciągnięcie'' elementu z listy. Jeśli chcemy uzyskać pojedynczy element, podajemy jego indeks w parze nawiasów kwadratowych:

roznosci = ['AGA', 23, 3.14, True]
kodon = roznosci[0]
print(kodon)
print(type(kodon))
AGA
<class 'str'>

Jak widać, podobnie jak w przypadku znaków w łańcuchu znaków, indeksy mają numery począwszy od 0, a ostatni indeks ma wartość o jeden niższą niż liczba elementów w liście. Długość listy możemy uzyskać, używając znanej na już z łańcuchów znaków funkcji len().

print(f"Długość listy: {len(roznosci)}")
print(f"Ostatni element: {roznosci[len(roznosci) - 1]}")
Długość listy: 4
Ostatni element: True

Nawiasem mówiąc, widać już pewne podobieństwa pracy z listami (i krotkami) do poznanych wcześniej operacji na łańcuchach znaków. Dalej będzie ich więcej.

Jeśli chcemy uzyskać określony element, licząc od tyłu, użyjemy ujemnego indeksu:

print(roznosci[-2])
3.14

Można też uzyskać elementy z określonego zakresu, podając indeks pierwszego elementu i elementu kolejnego po ostatnim.

print(roznosci[1:3])
[23, 3.14]

Warto zauważyć, że w ten sposób otrzymujemy jako wynik listę:

fragment_listy = roznosci[1:3]
print(type(fragment_listy))
<class 'list'>

Jeżeli nie podamy pierwszej liczby, domyślnie zostanie użyty pierwszy indeks, czyli 0.

print(roznosci[:3])
['AGA', 23, 3.14]

Analogicznie możemy nie podać drugiej liczby, w takim przypadku uzyskamy elementy do końca listy:

print(roznosci[1:])
[23, 3.14, True]

Z powyższego łatwo wywnioskować, że nie podając obu liczb uzyskamy całą listę:

print(roznosci[:])
['AGA', 23, 3.14, True]

Taki sposób wydaje się mało praktyczny, biorąc pod uwagę, że można po prostu wpisać samą nazwę listy, aby otrzymać jej wszystkie elementy, jednak taki zapis przydaje się, np. gdy dodamy trzecią liczbę:

print(roznosci[::2])
['AGA', 3.14]

Trzecia liczba oznacza ,,krok'', czyli co który element należy pobrać z listy. Podaliśmy 2, więc otrzymaliśmy co drugi element. Można oczywiście wpisać liczbę ujemną:

print(roznosci[::-2])
[True, 23]

Zastanów się, jak uzyskać listę z elementami w odwróconej kolejności?

Odpowiedź:

print(roznosci[::-1])
[True, 3.14, 23, 'AGA']

Otrzymujemy w ten sposób nową listę, ale oryginalna lista się nie zmienia. Za chwilę dowiemy się jak modyfikować listy.

Kopiowanie listy

Powyższy sposób określania zakresu elementów listy, można zastosować przy kopiowaniu listy:

zasady = ['A', 'T', 'G', 'C', 'U']
kopia = zasady[:]
print(zasady)
print(kopia)
['A', 'T', 'G', 'C', 'U']
['A', 'T', 'G', 'C', 'U']

Zapewne zastanawiasz się, czemu nie można zrobić tak:

kopia = zasady
print(zasady)
print(kopia)
['A', 'T', 'G', 'C', 'U']
['A', 'T', 'G', 'C', 'U']

Pozornie wszystko działa, ale przypomnij sobie, jak działają zmienne w Pythonie. Wyrażenie kopia = zasady spowoduje, że zarówno zasady, jak i kopia będą wskazywać na tę samą listę, zatem zmiana w jednej, będzie widoczna w drugiej. Wrócimy do tego tematu, kiedy poznamy sposoby modyfikacji list.

Drugi sposób kopiowania listy polega na użyciu funkcji list():

zasady = ['A', 'T', 'G', 'C', 'U']
kopia = list(zasady)
print(zasady)
print(kopia)
['A', 'T', 'G', 'C', 'U']
['A', 'T', 'G', 'C', 'U']

Trzeci sposób wykorzystuje metodę copy():

zasady = ['A', 'T', 'G', 'C', 'U']
kopia = zasady.copy()
print(zasady)
print(kopia)
['A', 'T', 'G', 'C', 'U']
['A', 'T', 'G', 'C', 'U']

Powyższe sposoby sprawdzają się dobrze w prostych listach zawierających liczby czy łańcuchy znaków. Niestety w bardziej złożonych przypadkach napotkamy problemy. Wrócimy do tego tematu w jednej z kolejnych lekcji.

Listy i pętle

Często gromadzi się elementy w listach po to, by je potem kolejno wykorzystać w jakiś sposób w programie. Jeśli zatem chcemy po kolei uzyskać pojedynczo każdy elementy listy, warto użyć w tym celu pętli (przeprowadzimy iterowanie):

kodony = ['AGA', 'CUC', 'ACU', 'AGA', 'UUG']
for kodon in kodony:
    print(kodon)
AGA
CUC
ACU
AGA
UUG

Można też w pętli wykorzystać fragment listy:

for kodon in kodony[:3]:
    print(kodon)
AGA
CUC
ACU

W pętli możemy też iterować kilka list jednocześnie, za pomocą funkcji zip():

seq_1 = ['A', 'T', 'G', 'T', 'C']
seq_2 = ['T', 'A', 'C', 'T', 'G']
for zasada_1, zasada_2 in zip(seq_1, seq_2):
    print(f"{zasada_1}-{zasada_2}")
A-T
T-A
G-C
T-T
C-G

Zadanie: Rozbuduj powyższy kod, aby sprawdzić, czy poszczególny zasady w parach są względem siebie komplementarne zgodnie z zasadą komplementarności.

seq_1 = ['A', 'T', 'G', 'T', 'C']
seq_2 = ['T', 'A', 'C', 'T', 'G']
for zasada_1, zasada_2 in zip(seq_1, seq_2):
    if (zasada_1 == 'A' and zasada_2 == 'T') or (zasada_1 == 'T' and zasada_2 == 'A') \
    or (zasada_1 == 'G' and zasada_2 == 'C') or (zasada_1 == 'C' and zasada_2 == 'G'):
        komplementarny = '+'
    else:
        komplementarny = '-'
    print(f"{zasada_1}-{zasada_2}: {komplementarny}")

Szukanie elementu w liście.

Aby sprawdzić, czy dany element znajduje się w liście, możemy wykorzystać, znaną nam już konstrukcję if w połączeniu z in. Poprzednio wyszukiwaliśmy za jej pomocą liter w ciągu znaków, teraz pomoże na sprawdzić, czy dany element występuje w liście:

kodony = ['AGA', 'CUC', 'ACU', 'AGA', 'UUG']
if 'AGA' in kodony:
    print('Jest alanina')
else:
    print('Nie ma alaniny')
Jest alanina

Jeśli chcemy zbadać ile razy dany element występuje, przyda nam się funkcja count():

print(kodony.count('AGA'))
2

Wiemy już jak sprawdzić, czy dany element znajduje się w liście, możemy nawet sprawdzić ile takich elementów jest, przydałaby się jeszcze możliwość zlokalizowania (czyli uzyskania indeksu) elementu w liście. Służy do tego funkcja index():

print(kodony.index('AGA'))
0

Zauważ, że został zwrócony tylko indeks pierwszej wartości.

Jeśli szukanego elementu nie ma w liście, to otrzymamy błąd:

print(kodony.index('GGA'))
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-38-b575108dd95c> in <module>
----> 1 print(kodony.index('GGA'))


ValueError: 'GGA' is not in list

Zatem, jeśli chcemy tego uniknąć, warto najpierw sprawdzić, czy element występuje:

kodon = 'GGA'
if kodon in kodony:
    print(f"Kodon {kodon} znajduje się pod indeksem {kodony.index(kodon)}")
else:
    print(f"Kodon {kodon} nie występuje na liście")
Kodon GGA nie występuje na liście

Szukanie można ograniczyć do fragmentu listy, podając kolejne parametry. Na przykład, jeśli chcemy wyszukać element między 3 i 5 elementem listy, napiszemy tak:

print(kodony.index('AGA',2, 4))
3

Jeśli chcemy szukać od konkretnego indeksu do końca, pomijamy ostatni argument:

print(kodony.index('AGA',2))
3

Zadanie

Napisz program, który poda indeksy wszystkich wystąpień danego elementu w liście.

# Tworzymy listę
kodony = ['AGA', 'CUC', 'ACU', 'AGA', 'UUG', 'AGA']
# Wyszukiwany kodon
kodon = 'AGA'
# Początek wyszukiwania
start = 0
# Poniższa pętla będzie się wykonywała dopóki zmienna 
# kontynuuj bedzie miała wartość True
kontynuuj = True
while kontynuuj:
    # Jeżeli w łańcuchu, począwszy od indeksu start...
    if kodon in kodony[start:]:   
        # kodon szukany jest od miejsca start
        # pobierany indeks wystąpienia szukanego kodonu
        indeks = kodony.index(kodon,start)
        # wydruk wyniku
        print(f"{kodon} znajduje się na pozycji {indeks}")
        # zmiana wartości start, kolejne szukanie będzie się 
        # odbywało od miejsca, w którym znaleziono ostatnio kodon +1
        start = indeks + 1
    # Jeśli nie znaleziono kodonu...
    else:
        # Zmienna kontynuuj przyjmuje wartość False
        # i pętla nie wykonuje się kolejny raz
        kontynuuj = False
    
AGA znajduje się na pozycji 0
AGA znajduje się na pozycji 3
AGA znajduje się na pozycji 5

Tworzenie listy z łańcucha znaków i z powrotem

Listę można utworzyć używając metody split():

peptyd = 'His Phe Val Thr Lys Lys'
aminokwasy = peptyd.split()
print(aminokwasy)
['His', 'Phe', 'Val', 'Thr', 'Lys', 'Lys']

W powyższym przykładzie łańcuch znaków został ,,pocięty'' w miejscach, w których występowała spacja a powstałe fragmenty zostały zapisane jako osobne elementy listy aminokwasy. Domyślnie metoda split() używa znaków białych (spacje, tabulatory itd.) ale może to być inny znak lub ciąg znaków:

peptyd = 'His Phe Val Thr Lys Lys'
aminokwasy = peptyd.split('h')
print(aminokwasy)
['His P', 'e Val T', 'r Lys Lys']

Można też odwrócić ten proces, z listy utworzyć ciąg znaków. Służy do tego metoda join():

peptyd = 'His Phe Val Thr Lys Lys'
aminokwasy = peptyd.split()
print(aminokwasy)
separator = "-"
peptyd = separator.join(aminokwasy)
print(peptyd)
['His', 'Phe', 'Val', 'Thr', 'Lys', 'Lys']
His-Phe-Val-Thr-Lys-Lys

Jest to trochę nieintuicyjne, ale metodę join() wywołujemy nie na liście, ale na ciągu znaków, który staje się separatorem. Powyżej utworzyliśmy zmienną separator, ale można pominąć ten krok:

peptyd = '-*-'.join(aminokwasy)
print(peptyd)
His-*-Phe-*-Val-*-Thr-*-Lys-*-Lys

Poznajmy jeszcze sposób rozbicia łańcucha znaków na poszczególne znaki i utworzenie z nich listy:

sekwencja = 'ATGACG'
nukleotydy = list(sekwencja)
print(nukleotydy)
['A', 'T', 'G', 'A', 'C', 'G']

Tworzenie listy z użyciem funkcji list() i range()

Do tworzenia list zawierający kolejne liczby, kolejne liczby parzyste itp. można tez zaprząc znana nam już funkcję range():

liczby = list(range(1, 6))
print(liczby)
[1, 2, 3, 4, 5]
liczby_parzyste = list(range(2, 11, 2))
print(liczby_parzyste)
[2, 4, 6, 8, 10]

Modyfikacje list

Zmiana elementu

Zmiana pojedynczego elementu listy jest dość intuicyjna:

dna = ['A', 'T', 'G', 'A', 'C', 'G']
print(dna)
dna[2] = 'C'
print(dna)
['A', 'T', 'G', 'A', 'C', 'G']
['A', 'T', 'C', 'A', 'C', 'G']

Jak widać ,,podmieniliśmy'' element w liście podając jego indeks w nawiasach kwadratowych ([]) i nową wartość po =.

Można też podmienić fragment listy:

dna = ['A', 'T', 'G', 'A', 'C', 'G']
print(dna)
dna[0:3] = ['C', 'C', 'C']
print(dna)
['A', 'T', 'G', 'A', 'C', 'G']
['C', 'C', 'C', 'A', 'C', 'G']

Przypominam, że jeśli podajemy zakres indeksów, to indeks, który oznacza koniec, nie wchodzi w ten zakres.

Zobaczmy, co się stanie, jeśli podany zakres do podmiany jest krótszy, niż podana lista nowych wartości:

dna = ['A', 'T', 'G', 'A', 'C', 'G']
print(dna)
dna[0:2] = ['C', 'C', 'C']
print(dna)
['A', 'T', 'G', 'A', 'C', 'G']
['C', 'C', 'C', 'G', 'A', 'C', 'G']

W takim wypadku podmianie uległy dwa elementy, trzeci został ,,wciśnięty'' w listę a pozostałe elementy ,,przemieściły się'' uzyskując większe indeksy. W efekcie lista się wydłużyła.

Jest to jakiś sposób na dodawanie nowych elementów do listy, ale do tego celu są dedykowane specjalne metody, o których za chwilę.

Sprawdźmy jeszcze, co się stanie, jeśli zrobimy coś takiego:

dna = ['A', 'T', 'G', 'A', 'C', 'G']
print(dna)
dna[0:3] = []
print(dna)
['A', 'T', 'G', 'A', 'C', 'G']
['A', 'C', 'G']

Tym razem lista się skróciła.

Dodawanie elementów listy

Używając metody insert(), można dodać element w dowolnym miejscu listy, podając indeks miejsca w liście, w którym należy go umieścić, pozostałe ,,przesuną się'':

dna = ['A', 'T', 'G', 'A', 'C', 'G']
print(dna)
dna.insert(1, 'C')
print(dna)
['A', 'T', 'G', 'A', 'C', 'G']
['A', 'C', 'T', 'G', 'A', 'C', 'G']

Do dodania elementu na końcu listy, przyda się metoda append():

dna = ['A', 'T', 'G', 'A', 'C', 'G']
print(dna)
dna.append('C')
print(dna)
['A', 'T', 'G', 'A', 'C', 'G']
['A', 'T', 'G', 'A', 'C', 'G', 'C']

Usuwanie elementów listy

Skoro wiemy już jak dodawać elementy, dobrze by było poznać sposoby usuwania ich. Jeden już znamy, teraz poznamy kolejne. Pierwszy z nich wykorzystuje polecenie del (nie jest to metoda listy!):

dna = ['A', 'T', 'G', 'A', 'C', 'G']
print(dna)
del dna[0]
print(dna)
['A', 'T', 'G', 'A', 'C', 'G']
['T', 'G', 'A', 'C', 'G']

Metoda pop() usuwa element listy z podanego indeksu, jeśli go podamy, a jeśli nie podamy, to usunięty zostanie ostatni. Można przy tym uzyskać usuwany element:

dna = ['A', 'T', 'G', 'A', 'C', 'G']
print(dna)
el_1 = dna.pop()
print(dna)
print(el_1)
el_2 = dna.pop(1)
print(dna)
print(el_2)
['A', 'T', 'G', 'A', 'C', 'G']
['A', 'T', 'G', 'A', 'C']
G
['A', 'G', 'A', 'C']
T

Kolejna metoda pozwala usunąć konkretny element, nawet jeśli nie znamy jego położenia na liście:

dna = ['A', 'T', 'G', 'A', 'C', 'G']
print(dna)
dna.remove('G')
print(dna)
['A', 'T', 'G', 'A', 'C', 'G']
['A', 'T', 'A', 'C', 'G']

Zauważ, że usunięty zostaje tylko pierwszy pasujący element.

Wróćmy na chwilę do pomysłu kopiowania list za pomocą operatora =. Poniższy przykład pokazuje, w czym tkwi problem:

seq_1 = ['A', 'T', 'G', 'A', 'C', 'G']
seq_2 = seq_1
print(seq_1)
print(seq_2)
seq_2[1] = '-'
print(seq_1)
print(seq_2)
['A', 'T', 'G', 'A', 'C', 'G']
['A', 'T', 'G', 'A', 'C', 'G']
['A', '-', 'G', 'A', 'C', 'G']
['A', '-', 'G', 'A', 'C', 'G']

Jak widać, nie stworzyliśmy odrębnej kopii listy, ale zarówno seq_1, jak i seq_2 wskazują na tę samą listę, zatem jeśli modyfikujesz listę, używając jednej z tych zmiennych, jest ona widoczna także w drugiej. Powyżej pokazałem, jak należy tworzyć rzeczywiste kopie list, choć także tamte sposoby mają swoje ograniczenia, do czego wrócimy później.

Czyszczenie listy

Czasem potrzebujemy wyczyścić całą listę, służy to tego metoda clear(), która usuwa z niej wszystkie elementy:

geny = ['atp1', 'atp4', 'atp6', 'atp8', 'atp9']
print(geny)
geny.clear()
print(geny)
['atp1', 'atp4', 'atp6', 'atp8', 'atp9']
[]

Łączenie list

Łączenie list można zrealizować na kilka sposobów. Pierwszy z nich, możesz w zasadzie wymyślić, wykorzystując powyższe informacje.

Zadanie Mamy dwie listy:

    geny = ['atp1', 'atp4', 'atp6', 'atp8', 'atp9']
    cox = ['cox1', 'cox2', 'cox3'] 

Dołącz zawartość listy cox do listy geny.

Rozwiązanie:

geny = ['atp1', 'atp4', 'atp6', 'atp8', 'atp9']
cox = ['cox1', 'cox2', 'cox3'] 
for gen in cox:
    geny.append(gen)
print(geny)
['atp1', 'atp4', 'atp6', 'atp8', 'atp9', 'cox1', 'cox2', 'cox3']

Zauważ, że ten sposób umożliwia modyfikację elementu przed dołączeniem go do listy, np.:

geny = ['atp1', 'atp4', 'atp6', 'atp8', 'atp9']
cox = ['cox1', 'cox2', 'cox3'] 
for gen in cox:
    geny.append(gen.upper())
print(geny)
['atp1', 'atp4', 'atp6', 'atp8', 'atp9', 'COX1', 'COX2', 'COX3']

Być może pokusi Cię, żeby zamiast iterować, przekazać całą listę cox do metody append(). Sprawdźmy zatem jaki będzie efekt takiej operacji:

geny = ['atp1', 'atp4', 'atp6', 'atp8', 'atp9']
cox = ['cox1', 'cox2', 'cox3']
geny.append(cox)
print(geny)
['atp1', 'atp4', 'atp6', 'atp8', 'atp9', ['cox1', 'cox2', 'cox3']]

Nie do końca tego oczekiwaliśmy, wygląda na to, że nie dodaliśmy elementów listy cox do listy geny, ale cała lista cox została dodana do listy geny jako jej kolejny (jeden!) element. Można to zresztą łatwo sprawdzić:

print(f"element 2: {geny[1]}, typ: {type(geny[1])}")
print(f"element 6: {geny[5]}, typ: {type(geny[5])}")           
element 2: atp4, typ: <class 'str'>
element 6: ['cox1', 'cox2', 'cox3'], typ: <class 'list'>

Jak widać, elementem w liście może być także lista. Wrócimy do tego zagadnienia później.

Kolejne dwa sposoby są krótsze i praktyczniejsze, o ile chcemy tylko dołączyć jedną listę od drugiej.

Pierwszy wykorzystuje metodę extend():

geny = ['atp1', 'atp4', 'atp6', 'atp8', 'atp9']
cox = ['cox1', 'cox2', 'cox3']
geny.extend(cox)
print(geny)
['atp1', 'atp4', 'atp6', 'atp8', 'atp9', 'cox1', 'cox2', 'cox3']

Wygląda to w sumie podobnie do powyższej próby łączenia list za pomocą metody append(), ale tym razem dodane zostały poszczególne elementy listy cox, a nie cała lista.

Drugi sposób wykorzystuje operator+ w połączeniu z =:

geny = ['atp1', 'atp4', 'atp6', 'atp8', 'atp9']
cox = ['cox1', 'cox2', 'cox3']
geny += cox
print(geny)
['atp1', 'atp4', 'atp6', 'atp8', 'atp9', 'cox1', 'cox2', 'cox3']

Sortowanie list

Sortowanie list jest dość ciekawym zagadnieniem. Istnieje wiele algorytmów sortowania i w ramach samodzielnych ćwiczeń umiejętności programistycznych warto spróbować samodzielnie napisać odpowiedni kod. Na razie jednak poznamy dwa sposoby automatycznego sortowania list.

Pierwszy z nich wykorzystuje metodę sort(). Zmienia ona uporządkowanie elementów w liście, na której wywołujemy tę metodę:

liczby = [3, 1, 12, 5, 7]
liczby.sort()
print(liczby)
lancuchy = ['Gly', 'Pro', 'Met', 'Ala', 'Ile']
lancuchy.sort()
print(lancuchy)
[1, 3, 5, 7, 12]
['Ala', 'Gly', 'Ile', 'Met', 'Pro']

Można także posortować listę odwrotnie, przekazując metodzie sort() argument reverse = True:

liczby = [3, 1, 12, 5, 7]
liczby.sort(reverse = True)
print(liczby)
lancuchy = ['Gly', 'Pro', 'Met', 'Ala', 'Ile']
lancuchy.sort(reverse = True)
print(lancuchy)
[12, 7, 5, 3, 1]
['Pro', 'Met', 'Ile', 'Gly', 'Ala']

Drugi sposób wykorzystuje funkcję sorted(). Nie zmienia ona samej listy, ale zwraca posortowaną kopię, którą możemy od razu wydrukować, albo przypisać do zmiennej:

liczby = [3, 1, 12, 5, 7]
liczby_posortowane = sorted(liczby)
print(f"{liczby = }")
print(f"{liczby_posortowane = }")
lancuchy = ['Gly', 'Pro', 'Met', 'Ala', 'Ile']
lancuchy_posortowane = sorted(lancuchy)
print(f"{lancuchy = }")
print(f"{lancuchy_posortowane = }")
liczby = [3, 1, 12, 5, 7]
liczby_posortowane = [1, 3, 5, 7, 12]
lancuchy = ['Gly', 'Pro', 'Met', 'Ala', 'Ile']
lancuchy_posortowane = ['Ala', 'Gly', 'Ile', 'Met', 'Pro']

Również w tym przypadku można posortować w odwrotnym porządku:

liczby = [3, 1, 12, 5, 7]
liczby_posortowane = sorted(liczby, reverse = True)
print(f"{liczby = }")
print(f"{liczby_posortowane = }")
lancuchy = ['Gly', 'Pro', 'Met', 'Ala', 'Ile']
lancuchy_posortowane = sorted(lancuchy, reverse = True)
print(f"{lancuchy = }")
print(f"{lancuchy_posortowane = }")
liczby = [3, 1, 12, 5, 7]
liczby_posortowane = [12, 7, 5, 3, 1]
lancuchy = ['Gly', 'Pro', 'Met', 'Ala', 'Ile']
lancuchy_posortowane = ['Pro', 'Met', 'Ile', 'Gly', 'Ala']

Krotki

Krotki (ang. tuples), zwane czasem tuplami są podobne do list, ale nie są modyfikowalne. W związku z tym wiele operacji, które działają na listach, będą także działały na krotkach, ale nie te, które wiążą się z ich modyfikacją. Nie możemy zatem dodawać, usuwać czy podmieniać elementów krotek, które zostały już wcześniej utworzone.

Tworzy się je podobnie jak listy, z tą różnicą, że zamiast nawiasów kwadratowych [] używamy nawiasów okrągłych ():

seq = ('A', 'T', 'G', 'A', 'C', 'G')
print(seq)
print(seq[2:6])
print(sorted(seq))
('A', 'T', 'G', 'A', 'C', 'G')
('G', 'A', 'C', 'G')
['A', 'A', 'C', 'G', 'G', 'T']

Zapewne zastanawiasz się: po co w ogóle stosować niemodyfikowalne krotki, skoro mamy do dyspozycji znacznie bardziej wszechstronne listy? Rzeczywiście, zapewne, jak wspomniałem na początku tej lekcji, będziesz używał znacznie częściej list, są jednak pewne powody, dla których można sięgnąć po krotki. Czasem z góry wiadomo, jakie elementy będą przechowywane w kolekcji i, co więcej, dobrze by było je zabezpieczyć przed choćby przypadkową zmianą. Ponadto krotki zajmują w pamięci mniej miejsca. Zapewne w prostych programach, które będziesz pisać na tym kursie, będzie to praktycznie niezauważalne, ale jeśli w przyszłości przyjdzie Ci pisać większe projekty, może warto będzie sobie o tym przypomnieć.

Last updated on 19 Nov 2020
Published on 19 Nov 2020