4. Tuple

Napomena: Sam pojam tuplea (torke) je prilično jednostavan, i ako vas zanima samo sintaksa tuplea, preskočite na poglavlje 4.1. Ovde je dato poređenje nekoliko pristupa rješavanju istog problema, da vidimo koji je bolji i da vidimo zašto je tuple uopšte nastao.

Prije nego što počnemo, jedno pitanje - kad ste poslednji put išli u prodavnicu? Nekad vam se znalo desiti da napravite spisak za kupovinu, koji zna izgledati ovako:

  • Krompir - 2 kg
  • Paradajz - 0.5 kg
  • Krastavci - 0.5 kg
  • Brašno - 1 kg

Sa dosadašnjim znanjem, znamo da bi ovo bila lista, svaka stvar sa spiska je jedan element liste. Ali pitanje je, lista čega? Pa, da vidimo šta su nam opcije:

Opcija 1: Lista stringova

Zvuči logično, svaka vrsta sa spiska odozgo je jedan element naše liste i sve bi radilo savršeno dok ne biste došli do vage. Tamo treba da uporedite masu onog što se izvagali, sa onim što imate na spisku, da vidite treba li dodati još ili ste pretjerali niko ne pogodi tačno. Tu imate mali problem jer imate string, a ne broj, i to se taj broj nalazi negdje u sredini stringa, ne na samom kraju.

In [3]:
spisak = ['Krompir - 2 kg', 'Paradajz - 0.5 kg']
trenutnoKrompira = 1 # kg, ne komada

# Kako sad lako uporediti trenutno stanje sa željenim?!

Opcija 2: Mješovita lista, string i broj

Pametniji nego maloprije, razdvojićemo naziv proizvoda i željenu masu u dva elementa liste, što će nam olakšati operacije poređenja hoće, malo sutra. Sad nam se nazivi stvari nalaze na neparnim indeksima, a količine na parnim ili je obrnuto?, kad prolazimo kroz listu moramo preskakati po dva elementa, previše matematike za nešto tako jednostavno.

In [5]:
spisak = ['Krompir', 2, 'Paradajz', 0.5]

# Trenutno kupujem drugu stvar sa svog spiska
trenutnaStvar = spisak[1]

# Odmah poslije imena stvari je kolicina
kolicina = spisak[1 + 1]

# Mooožda sam pobrkao indekse....
print('Treba da uzmem', trenutnaStvar, 'i to', kolicina, 'kg.')
Treba da uzmem 2 i to Paradajz kg.

Rekoh da niko ne koristi mješovite liste...

Opcija 3: Lista lista

Ova je najbolja, svaki element je lista od dva elementa, jedan je naziv, drugi količina. Nemamo problema sa indeksima, odvojena je količina od naziva, svi srećni. Mora da sam lagao u vezi mješovitih lista, vidi se da imaju neku prednost:

In [6]:
spisak = [
    ['Krompir', 2],
    ['Paradajz', 0.5]
]

# Nemamo problema sa indeksima, količine su jasno odvojene, ma milina

Pa, i nisam baš.

Kod radi ono što mu je namjena, to nije problem. Veći je problem navika - kako vi očekujete da se koristi lista? Poslije ko zna koliko napisanih linija koda, kad vidite listu, prvo što vam pada na pamet je kratka for petlja, koja će proći kroz elemente liste i obraditi svaki pojedinačno. Ovo vrijedi za spoljašnju listu, jer je svaki element sa spiska nezavisan, ali ne i za unutrašnje liste - elementi nisu nezavisni, već zajedno čine jednu cjelinu i svaki se obrađuje na poseban način. Drugi problem je što liste mogu da rastu i da se smanjuju, što iako odgovara spoljašnjoj listi, nema smisla za unutrašnje liste.

Da bismo dobili konačno (ispravno) rješenje, saznajmo prvo šta je to tuple.

4.1. Gdje početi?

Kako tradicija nalaže, prvo se napravi jedan tuple. Slično listi, to je spisak elemenata, odvojenih zarezom, a okružen malim zagradama (u većini situacija zagrade nisu obavezne, ali nije loša navika pisati ih). Nešto kao:

In [37]:
trenutnoVrijeme = 18, 7, 34
print('Ova linija je napisana u', trenutnoVrijeme)
Ova linija je napisana u (18, 7, 34)

Iako imaju mnogo sličnosti, lista i tuple se najviše razlikuju po namjeni:

Lista predstavlja grupu, međusobno nezavisnih elemenata, obično istog tipa. Tuple predstavlja grupu elemenata, koji čine jednu logičku cjelinu, često različitog tipa

Kao i lista, tuple podržava indeksiranje i sjeckanje za pristup svojim elementima. Za razliku od liste, tuple se nakon kreiranja ne može mijenjati.

In [38]:
trenutnoVrijeme = (18, 11, 12)

# Možemo indeksirati
print('Sad je', trenutnoVrijeme[0], 'časova')

# Možemo sjeckati
print('Na digitalnom satu prikaži', trenutnoVrijeme[0:2])

# Ali nema mijenjanja
trenutnoVrijeme[0] = 19
Sad je 18 časova
Na digitalnom satu prikaži (18, 11)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-38-55c7c00503fb> in <module>()
      8 
      9 # Ali nema mijenjanja
---> 10 trenutnoVrijeme[0] = 19

TypeError: 'tuple' object does not support item assignment

Opcija 4: Lista tupleova

Sad kad smo vidjeli šta je tuple, hajde na napravimo i ovu konačnu verziju spiska za kupovinu - lista tupleova.

Zašto tuple? Svaka stvar sa spiska je logička cjelina, sastavljena od elementata različitih tipova, naziva i količine.
Zašto lista? Stvari sa spiska su nezavisne i svaku ćemo obrađivati pojedinačno. Takođe, možemo ih dodavati i brisati iz liste.

Sa svim ovim rečenim, hajde da vidimo i to čudo:

In [22]:
spisak = [
    ('Krompir', 2),
    ('Paradajz', 0.5)
]

# Nemamo problema sa indeksima, količine su jasno odvojene i najbitnije, ima smisla

4.2. Raspakivanje tupleova

Da ne znate da postoji, ne biste znali da vam treba.

Ideja je "jednostavna" - napravite tuple, koji nema konkretne vrijednosti, već nazive promjenljivih kao elemente. Zatim, takvom tupleu dodjelite neki drugi tuple, sa normalnim, konkretnim vrijednostima. Time se svakoj promjenljivoj iz prvog tuplea dodjeli odgovarajuća vrijednost iz drugog. Na kraju, svaku od tih promjenljivih iz prvog tuplea koristite posebno. Huh, zvuči komplikovano. Nije:

In [39]:
# Tuple sa konkretnim vrijednostima
trenutnoVrijeme = (18, 29, 54)

# Tuple sa promjenljivim kao elementima, dodjeljujemo mu tuple sa konkretnim elementima
(sati, minuta, sekundi) = trenutnoVrijeme

# Sad koristimo elemente odvojeno
print('Sada je ', sati, ':', minuta, ':', sekundi, sep='')

# Zagrade nisu obavezne
dan, mjesec, godina = 12, 1, 2016
print('Danas je ', dan, '/', mjesec, '/', godina, sep='')

# Česta primjena - zamjeni vrijednosti
a = 1
b = 2
print('a =', a, 'b =', b)

a, b = b, a
print('a =', a, 'b =', b)

# Naravno, dimenzije se moraju poklapati
(sati, minuta) = trenutnoVrijeme
Sada je 18:29:54
Danas je 12/1/2016
a = 1 b = 2
a = 2 b = 1
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-39-087146d7dc46> in <module>()
     21 
     22 # Naravno, dimenzije se moraju poklapati
---> 23 (sati, minuta) = trenutnoVrijeme

ValueError: too many values to unpack (expected 2)

Index