Pythoni string, jada ja ennik

From Wikiversity

< 6. nädala teemad

Struktuursed andmetüübid[edit]

Python'i põhiandmetüüpide hulgas ei ole klassikalist massiivi (array), vaid selle keele puhul räägitakse jadast (sequence). Pythonis eristatakse kolme tüüpi jadasid:

  • string
  • jada ehk list
  • ennik ehk ennik

Klassikalise massiivina ei käitu neist ükski, indeksite kasutamise võimalus on aga omane neile kõigile.

Jada[edit]

Jadast üldiselt: jada elemendid on organiseeritud järjestikku ja nendele pääseb ligi indeksi kaudu, mis näitab elemendi kaugust jada algusest ehk elemendi järjekorranumbrit. Kogu selline struktuur on ülesehitatud jadamisi – üks element järgneb teisele. Ja teda salvestatakse samuti jadamisi. Elementide (jada liikmete) nummerdamine algab 0-st ja seega viimase elemendi number on N-1 (kui jadas on N elementi). Jada pikkuse saab teada len()-funktsiooniga:

N = len(jada)

Järgnev näide näitab, kuidas toimub indekseerimine jadas pikkusega N.

23 56 875 45 567      
0 1 2 3 4 ... N-2 N-1

Alternatiivne indekseerimine tehakse negatiivsete indeksitega. Sel juhul on N-elemendilise jada indeksid vahemikus -N kuni -1.

23 56 875 45 567      
-N -(N-1) -(N-2) ... -4 -3 -2 -1

Operaatorid[edit]

Sõltuvalt jadasse pandud elementide andmetüüpidest saab nendele rakendada kõiki tavalisi operaatoreid (st tehteid), mis sellist tüüpi andmetega opereerida oskavad. Kui jadas on täisarvud, saab nendega arvutada (kasutada aritmeetikaavaldistes), neid võrrelda (kasutada loogikaavaldistes) ja loomulikult sisestada ning välja trükkida. Jada elemente saab mõne operatsiooni jaoks kasutada korraga, mõnel puhul on aga vaja sealt elemente ükshaaval kätte saada. Korraga kasutamiseks on tavaliselt keeles defineeritud funktsioonid, mi terve jadaga töötada oskavad.

Spetsiaalselt jada jaoks kehtivad operaatorid on nii jada elementide väljalõikamiseks (nende ükshaaval kasutamiseks) kui ka teheteks terve jadaga.

Lõige[edit]

Jadast on võimalik tükke "välja lõigata" (ingl slicing).

jada[i1:i2]

Näites lõigatakse jadast välja elementide alamjada, mis algab i1 elemendiga (kaasaarvatud) ja lõppeb i2 elemendiga (väljaarvatud).

jada[i]

Sarnaselt saab jadast välja lõigata üksikut elementi. Jadast eraldatakse järjekorranumbriga i näidatud element, täpsemalt küll i-1 esimene element, sest nummerdamine algab 0-ga. Nii saab jada iga elemendiga ükshaaval midagi teha.

Kui jätta pikema lõike juures üks indeksitest ära, siis algusindeksi puudumisel tehakse lõige jada algusest ning lõpuindeksi puudumisel tehakse lõige viimase elemendini. Vt järgmist näidet:

jada[:i2]      jada[i1:]

Lõiked võivad olla ka keerulisemad: laiendatud lõige (extended slicing) lubab lisaks lõike pikkusele määrata ka sammu (näiteks võtta stringist märke üle ühe, kui sammuks on 2). Samm lisatakse kandilistesse sulgudesse kolmandaks arvuks. Sammu -1 puhul pööratakse jada tagurpidi.


Kordamine[edit]

Jada on võimalik korrutada täisarvuga ja saada sel viisil korduvate elementidega uus ja suurem jada:

jada * täisarvuline_avaldis

Jada korratakse nii mitu korda, kui nõuab avaldis (lihtsamal juhul on avaldise kohal täisarv või täisarvuline muutuja). Tehte tulemusena tekib uus jada.

Liitmine ehk konkateneerimine[edit]

Kaks jada saab liita uueks jadaks - mõlema jada elemendid paigutatakse üksteise järele.

jada1 + jada2

Tekkivasse uude jadasse lisatakse kõigepealt jada1 liikmed ja seejärel jada2 liikmed. Jadad peavad olema sama tüüpi, st stringi ja listi liita ei saa. Tõsisemaks tööks liitmistehet siiski ei soovitata, sest väidetavalt on tegemist aeglase operatsiooniga ja tuleks otsida/kasutada pigem vastavate andmetüüpide meetodeid.

Jadasse kuuluvuse kontrollimine[edit]

On võimalik kontrollida, kas mingi väärtus / element kuulub jadasse:

asi in jada 
asi not in jada 

Kontrollimiseks kasutatakse in operaatorit. Stringi puhul saame teada, kas vastav märk esineb stringis (sest string on jada märkidest). Vastus on tõeväärtustüüpi true või false. Listi ja enniku puhul saab teada objekti kuulumise jadasse. Operaator not in kontrollib vastupidi „mittekuulumist“ jadasse.

Standardfunktsioonid[edit]

Kõigi jada tüüpide jaoks on olemas mitmed sisefunktsioonid (build-in functions): Teisendusfunktsioonide abil saab muuta ühte tüüpi muutujad teist tüüpi muutujateks. Näiteks saab suvalisest arvust teha stringi või stringist listi. Vastavad funktsioonid on str(), list(/code)<> ja tuple(). Töötavad ka funktsioonid, nagu

max(jada) - tagastab suurima väärtuse
min(jada) - tagastab vähima väärtuse
sorted(jada, reverse = True) - sorteerib jada, tulemuseks on uus jada (vana säilub); lisades parameetrite loetellu reverse = True, sorteeritakse jada tagurpidi.
sum(jada, init = algväärtus) – summeerib jadas olevad e väärtused, kui seda teha saab, init abil saab summa algväärtustada.

Stringid[edit]

Stringide eraldamiseks muust programmitekstist kasutatakse jutumärke ja/või ülakomasid. Kasutamisel on nad ühesuguste omadustega. Märgitüüp (üks suvaline sümbol) Pythonis puudub. Seda asendab string pikkusega 1. Stringi saab käsitleda ühe skalaarse väärtusena, kuid samas on ka võimalik vaadelda stringi sümboleid jadana ja nende jaoks kasutada jada operaatoreid.

Operatsioonid[edit]

Eespool jada juures kirjeldatud operatsioone sobib reeglina teha ka stringidega. Näiteks stringist osade väljalõikamine toimub eespool kirjeldatud loogika kohaselt indeksite abil:

nimi = "Maali"
print(nimi[1]) -> 'a'
print(nimi[2:]) -> 'ali'

Stringi "puhastamiseks" või stringitüüpi muutuja loomiseks (kui sinna midagi asjalikku kirjutada ei ole) saab talle omistada tühja stringi:

nimi = "" 

või kasutada funktsiooni

del(nimi)

Stringe võrreldakse omavahel toetudes kooditabelile (märk on väiksem kui tema kood on väiksem). Võrrelda võib kahte tervet stringi korraga (st seda ei ole vaja programmis teha märk haaval). Vastavalt kooditabelile saame näiteks järgmise võrdlemise tulemuse:

"sääsk" > "elevant" -> True

Tuleb ka arvestada, et suur- ja väiketähed on erinevad.

Operaatoriga in saab küsida märgi kuulumist stringi.

Moodul string[edit]

Lisavõimalusi stringide töötlemiseks annab moodul string, mida saab programmis kasutusele võtta käsuga:

import string

Mõned näited mooduli võimalustest on eeldefineeritud stringid (nn stringkonstandid), mida saab programmides kasutada (näiteks selleks, et kontrollida mõne sümboli kuulumist suurtähtede hulka (tugineb ASCII-tabelile ning seega ei ole lokaliseeritav):

string.ascii_uppercase – suurtähed  'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
string.ascii_lowercase – väiketähed  'abcdefghijklmnopqrstuvwxyz'
string.ascii_letters – kõik tähed  'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
string.digits – numbrid  '0123456789'

Lisaks string-konstantidele on selles moodulis ka vajalikke funktsioone/meetodeid, mida tasuks tervikuna uurida Pythoni dokumentatsioonist: The Python Standard Library. Stringi on juba eelmistes versioonides soovitatud kasutada kui objekti, st string on klass, millel on meetodid, mitte funktsioonid. Pythoni versioonis 3.x ongi funktsioonide kasutamise võimalus kadunud.

Järgmises lauses muudab meetod upper() stringis lause olevad tähed suurtähtedeks, tekitades samal ajal uue stringi. Uuele stringile pannakse vana nimi:

asi = asi.upper()

Näited stringist sümbolite ükshaaval eraldamiseks (ja trükkimiseks) kasutades jadade töötlemiseks ettenähtud for-tsüklit. Esimene näide käitub listiga kui massiiviga, "teeb" for-tsükli ja range()-funktsiooni abil arvud 0 .. 4 ja kasutab neid stringis indeksitena:

# Kasutatakse indeksit, eraldatakse järjest kõik tähed.
# Indeksi piirid on 0 kuni stringi pikkus (viimane väljaarvatud)
s6na = "abcde"
for i in range(0, len(s6na)):
    print(s6na[i])

Täpselt sama töö teeb ära ka järgmine kood ja on nö "pütoonilisem". Kasutatakse for-tsükli oskust itereeruda mööda jada mingeid indekseid arvestamata:

# Kui indeks ei anna lisaväärtust, ei ole mõtet teda kasutada
s6na = "abcde"
for t2ht in s6na:
    print(t2ht)

Kui string panna kolme paari ülakomade või jutumärkide vahele, võib seal sees näiteks kasutada tavalisi reavahetusi teksti vormindamiseks (ei ole vaja lisada \n või kirjutada korduvaid print-lauseid). Selline võimalus on hea, kui oleks vaja esitada teksti võimalikult WYSIWYG-i kujul – näiteks soovides oma programmiga veebi jaoks HTML-i genereerida.

Pythoni stringid on mittemuudetavud (immutable). See tähendab, et kui stringi muudetakse (mida saab loomulikult teha), siis tegelikult tekib mällu uus string. Õnneks programmikirjutaja seda reaalselt ei näe, kuid selle faktiga tuleb arvestada. Näiteks ei luba interpretaator ühes stringis tähtede või lõikude asendamist. Omistamine nimi[2] = "a" lõppeb veateatega.

String kui objekt[edit]

Paar sõna lisaks eelpool mainitud objektide jutule. Python on objekt-orienteeritud keel. Stringi vaadeldakse Pythonis kui objekti. Objektist võime me mõtelda (esialgu) kui muutujast. Tema jaoks on Pythonis kirjeldatud meetodid (ehk tegevused), mida objekt teha oskab. Meetodi käivitamine toimub liitnime abil: objekti_nimi.meetodi_nimi. Kui moodustada string, siis on kohe olemas ka meetodid tema töötlemiseks.

Seega juba eespool olnud näites lause = lause.upper() on lause stringi-tüüpi objekt ning kasutatakse stringi-objektidega kaasnevat meetodit upper(). Rohkem oleme seni harjunud funktsiooni kasutamisega, seega kirjapilt lause = upper(lause) tundub arvatavasti kodusem. Paraku see uuemas Pythonis enam ei toimi.

Järgnevalt mõned näited stringi kui objekti kasutamisest (selgitus allpool):

# Stringi esitäht tehakse suureks ja loendatakse „a“ esinemine stringis
nimi =  "maali maasikas"
nimi = nimi.capitalize()   # Esitähe suurendamise meetod
loendur = nimi.count("a")     # Alamstringide loendamise meetod
print("Nimi on ", nimi, "ja selles on ",loendur, " a-d.")

Väljatrükk on:

Nimi on  Maali maasikas ja selles on  5  a-d.

Stringi-tüüpi muutujaks ehk objektiks on nimi. Stringi kui objektiga on seotud meetodid capitalize(), count() jms. Et nime esitäht suureks teha, käivitatakse meetod nii: nimi.capitalize(). Kui meil oleks eraldi string perekonnanimi, saaks tema esitähe suureks muuta perekonnanimi.capitalize() abil. Muutujanimi liitnime alguses ütleb, millise stringiga tuleb vastav toiming teha.

NB! Võrreldes Python 2.x-ga on keelest kadunud mitmed stringifunktsioonid ja asemele tulnud (või ainsana kasutusse jäänud) stringi kui objekti meetodid. Seega ei tasu taas imestada, kui mõni veebist leitud näide keeldub tööle minemast.

Listid[edit]

List on andmeüksuste jada, kus üksikule elemendile pääseb ligi indeksi kaudu või kasutades for-tsüklit. Sarnaselt stringiga näitab indeks elemendi paiknemise kaugust listi alguspunktist. Listi elemendid saavad olla suvalist andmetüüpi ja nad saavad olla erinevad. Listi saab elemente lihtsalt lisada ja sealt neid ka kustutada. Liste saab ühendada ja tükkideks jagada.

Listi loomiseks saab kasutada omistuslauset ja listi määramiseks kandilisi sulge [].

asjade_list = ['hobune', 12, 3.45, 'pann', ['list', 'listis']]

Näites toodud listi viimane element on omakorda list ja tema elementide kätte saamiseks tuleb kasutada kahte indeksit (vt näide allpool). Üksikute elementide ja lõikude eraldamine listist töötab sarnaselt stringile (jälgi indekseid:

asjade_list[3] -> 'pann'
asjade_list[4][1] -> 'listis'

Listi elemendile omistamine asendab ühe väärtuse teisega:

asjade_list[3] = 'kastrul' 
> ['hobune',12,3.45,'kastrul',['list', 'listis']]

Listist saab kustutada del käsuga indeksi järgi:

del asjade_list[2] 
> ['hobune',12,'kastrul',['list', 'listis']]

Operaatorid[edit]

Liste saab võrrelda (suurem, väiksem, ...). Liste võrreldakse element haaval, kuni leitakse erinevus ja selle järgi otsustakse võrdumine, mittevõrdumine jms.

Listist saab eraldada üksikut liiget või lõiku, sealjuures indeksite kasutamine on samasugune kui stringide puhul. Erinevuseks on, et igale indeksile vastab terve element. Üheks listi elemendiks võib olla teine list. Sel juhul tekib kahemõõtmeline struktuur.

Listid on muudetavad (mutable), st neid saab muuta osade kaupa, näiteks mõnda elementi välja vahetada. See on oluliseks erinevuseks võrreldes stringiga.

Operaatoritega in ja not in abil saab kontrollida elemendi kuulumist või mittekuulumist listi (sarnaselt stringile).

'pott' in asjade_list
> False
'kastrul' in asjade_list
> True

Sisefunktsioonidest sobib kasutada (ja töötavad sarnaselt nagu stringidegagi):

  • len() - pikkuse, st listi elementide arvu leidmiseks;
  • max() ja min() - suurima ja vähima väärtusega elemendi leidmiseks; see töötab normaalselt siis, kui listi elemendid on ühte tüüpi
  • sorted() ja reversed() - sorteerimine toimub ASCII tabeli järgi, st mitte tähestiku järgi. St suured tähed on kõik väikestest tähtedest eespool.

Ennik[edit]

Ennik (ingl tuple) on väga sarnane listile. Eestikeelse vastega on veidi raskusi. Mõned variandid, mis internetist silma jäid: rida, järjend, ennik (standardile vastav), korteež (inglise-eesti sõnastiku tõlge, kasutusel pigem matemaatikas). Siin saab teda vastavalt standardile ennikuks kutsutud. Programmis kasutatakse enniku kirjeldamiseks ümarsulge (erinevalt listist, kus oli kandilised sulud).

Ennikute moodustamine ja temast lõigete tegemine on sarnane listiga:

ennik = ('lill', 'liblikas', 13, 'ohakas', 1234, 65.345)
ennik[2]
> 13

Ennik on muudetamatu (immutable), st tema elemente ükshaaval muuta ei saa. See ongi peamine (ja oluline erinevus võrreldes listiga). Enniku muutmiseks tuleb moodustada uus ennik, näiteks:

uus_ennik = (ennik[0], ennik[4], ennik[3]) -> ('lill','ohakas',13)

Operaatorid[edit]

Ennikuid saab võrrelda ja nendest lõikeid teha sarnaselt listile. Sisefunktsioonidest töötavad nö info pärimise funktsioonid (len(), max(), min() ..), kuid mitte need, mis enniku sisu muuta tahaksid.

Järgevalt väike näide listi töötlemise kohta programmis. Listi kõigi elementide töötlemiseks sobib kasutada for-tsüklit. Eespool oli näide stringi kohta. Sarnaselt saab toimida listiga:

# Kõigepealt luuakse list sisestatud nimedest (tühi string lõpetab sisestuse)
# ja seejärel trükitakse see nimekiri välja
# Sisesatmiseks while-tsükkel, väljundiks for-tsükkel

nimed = []                 # Teeme tühja listi
uus_nimi = input("Sisesta nimi ")
while uus_nimi != "":      # Tsükkel töötab kuni sisendiks midagi on
    nimed += [uus_nimi]    # Nimi lisatakse listi
    uus_nimi = raw_input("Sisesta nimi, lõpetamiseks Enter ")
for nimi in nimed:         # Trükitakse välja kõik nimed
   print(nimi)
print("Tänan tähelepanu eest!")

Lisaks väljundile võib elementidega teha ka muud.

Kasutamine[edit]

Ehkki ühte listi saab koondada erinevat tüüpi andmeid, ei ole selliste listidega eriti palju pihta hakata. Andmete süstemaatiliseks töötlemiseks on eelistatud sarnase struktuuriga andmestikud. Seega tasub oma liste planeerida ja kasutada suurema hulga sarnaste andmete hoidmiseks. List saab koosneda teistest listidest ja selliselt moodustub kahemõõtmeline struktuur (mida võib endale ka maatriksina ette kujutada).

< 6. nädala teemad