1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
|
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" type="text/css" href="/css/codeq.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" />
</head>
<body>
<h1>Kako kličemo metode</h1>
<p>Funkcijam, ki smo jih srečevali doslej, smo, da so kaj naredile, morali dati
podatke, na katerih so delale. Funkcija <code>len</code> kot argument
zahteva seznam ali niz, katerega dolžino bi radi izvedeli. Funkcija
<code>input</code> kot argument želi niz z vprašanjem, ki bi ga radi
zastavili uporabniku. Razen argumentov, ki jih podamo, te funkcije nimajo
drugih podatkov (vsaj ne, da bi mi vedeli zanje).</p>
<p>Ko smo se učili o seznamih, pa smo mimogrede naleteli na neko nenavadnost:
za dodajanje novega elementa v seznam nismo poklicali funkcije, ki bi ji
podali seznam in element (na primer <code>append(imena, "Ana")</code>),
temveč smo morali napisati ime seznama, ki mu je sledila pika in
<code>append</code>, kot argument pa smo navedli le element, ki smo ga
želeli dodati, torej <code>imena.append("Ana")</code>.</p>
<pre>>>> imena = []
>>> imena.append("Ana")
>>> imena.append("Berta")
>>> imena
['Ana', 'Berta']</pre>
<p><code>append</code> je očitno nenavaden, ne kličemo ga tako kot druge
funkcije. Funkcija <code>append</code> "pripada" seznamu; zato mu pravimo
<code>imena.append</code>. Naredimo še en seznam.</p>
<pre>
>>> teze = []
>>> teze.append(55)
>>> imena.append("Cene")
>>> imena
['Andrej', 'Branka', 'Cene']
>>> teze
[55]</pre>
<p>Vsak seznam ima svoj <code>append</code>: <code>imena</code> imajo
<code>imena.append</code> in <code>teze</code> imajo
<code>teze.append</code>.</p>
<p>Takšnim funkcijam pravimo <em>metode</em>. Klic <code>imena.append</code>
si predstavljamo, kot da <em>seznamu <code>imena</code> rečemo "dodaj si
element" <code>"Cene"</code></em> in klic <code>teze.append(55)</code>
pomeni, da <em>seznamu <code>teze</code> rečemo "dodaj si element"
<code>55</code></em>.</p>
<p>Pika, <code>.</code> izraža nekakšno pripadnost, vsebovanost. Ko smo
spoznali module, smo videli, da z <code>math.sqrt</code> pridemo do
"math"ove funkcije z imenom "sqrt". Z <code>imena.append</code> zahtevamo
"imenovo" metodo "append". In z <code>teze.append</code> "tezovo" metodo
"append".</p>
<p>Takšnih metod je še veliko: takole prosimo niz <code>ime</code>, naj nam
pove, koliko črk "n" vsebuje.</p>
<pre>>>> ime = "Benjamin"
>>> ime.count("n")
2</pre>
<p>Takole pa niz <code>fname</code> vprašamo, ali se konča s "torrent":
<pre>>>> fname.endswith("torrent")
True</pre>
<p>Kako bi Benjamina spremenili v Benjamaxa? Težko: kot vemo, so nizi
nespremenljivi (tako kot terke; od vsega, o čemer smo govorili prejšnji
teden, lahko spreminjamo samo sezname). Pač pa lahko vprašamo niz, kako bi
bil videti, če "min" zamenjano z "max".</p>
<pre>>>> ime.replace("min", "max")
'Benjamax'</pre>
<p>Metode niso povezane s tem, ali je niz shranjen v spremenljivki ali ne.
Metodo moremo poklicati tudi na nizu "kar tako".
<pre>>>> "Maja".lower()
'maja'</pre>
<p>So z metodami obdarjeni samo nizi? Je to edinstven primer objektov v
Pythonu, ki imajo metode? Ne, nič ne bi moglo biti dalj od resnice! Skoraj
vsaka reč v Pythonu ima metode (ali vsaj nekaj podobnega). Celo običajna
števila imajo metode, čeprav zgolj tehnično in z zelo čudnimi imeni, kot
lahko vedoželjen študent hitro preveri:
<pre>>>> (-231).__abs__()
231</pre>
<p>Med tipi, ki smo jih spoznali doslej, pa imajo uporabe vredne metode nizi
in seznami. V okviru predavanj ne bomo podrobneje spoznavali vse mogočih
podatkovnih tipov. Temeljiteje pa bomo pogledali metode nizov, seznamov
in podobnih reči, ki jih pri programiranju v Pythonu vsakodnevno
uporabljamo. Obenem bomo tako dobili vtis, kako te reči izgledajo. Najprej
nizi.</p>
<h2>Metode nizov</h2>
<p>Nekaj smo jih že spoznali: <code>count</code>, <code>replace</code> in
<code>lower</code>. Zadnja ima sestro, <code>upper</code>, ki vrne niz,
pri katerem so vse črke pretvorjene v velike črke.</p>
<pre>>>> "Maja".lower()
'maja'
>>> "Maja".upper()
'MAJA'</pre>
<p>V žlahti z njima sta še (ne posebej uporabna) <code>capitalize</code> in
<code>title</code>.</p>
<pre>
>>> "benjamin".capitalize()
'Benjamin'
>>> "tole je stavek, ki ga bomo povelikocrkali po anglesko".title()
'Tole Je Stavek, Ki Ga Bomo Povelikocrkali Po Anglesko'</pre>
<p>Da ne bi kdo pozabil, za vsak slučaj še enkrat spomnimo: te metode ne
spreminjajo niza, temveč vračajo nove nize. Nizi ostanejo takšni, kot so
bili. Po tem primeru bi moralo biti jasno, kaj ne deluje in kako je
potrebno pisati, da bo delovalo.
<pre>>>> s = "benjamin"
>>> s
'benjamin'
>>> s.capitalize()
'Benjamin'
>>> s
'benjamin'
>>> s = s.capitalize()
>>> s
'Benjamin'</pre>
<p>Metodo <code>count</code> smo že spoznali. Povejmo le še, da lahko išče
tudi daljše podnize, ne le posamezne znake.</p>
<pre>>>> "Maja".count("a")
2
>>> "Maja".count("aj")
1</pre>
<p>Poleg <code>count</code> imamo tudi nekaj funkcij, ki povedo, kje v nizu
se nahaja določen podniz. Prvi sta <code>find</code> in <code>index</code>.
</p>
<pre>>>> s
'Benjamin'
>>> s.find("jam")
3
>>> s.index("jam")
3</pre>
<p>Edina razlika med njima je v tem, kaj storita, če iskanega niza ni.
<code>find</code> vrne -1, <code>index</code> pa javi napako.</p>
<pre>>>> s.find("maj")
-1
>>> s.index("maj")
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
ValueError: substring not found</pre>
<p>Če se dani podniz pojavi večkrat, bosta funkciji vrnili indeks prve
pojavitve - razen, če jima z dodatnimi argumenti povemo, od kod naprej
naj iščeta. Poleg <code>find</code> in <code>index</code> obstajata še
funkciji <code>rfind</code> in <code>rindex</code>, ki iščeta s konca in
tako vrneta zadnjo pojavitev podniza v nizu.</p>
<p>Mimogrede smo že omenili tudi preprosto, a zelo uporabno funkcijo
<code>endswith</code>, ki pove, ali se niz konča s podanim podnizom.
Poleg njega obstaja še <code>startswith</code>, ki pove ali se niz
<em>začne</em> z danim podnizom.</p>
<p>Metode <code>ljust</code>, <code>rjust</code> in <code>center</code>
dopolnijo niz s presledki z leve, z desne ali z obeh strani, tako da je
dolg toliko, kot želimo. Takole napihnemo Benjamina na 15 znakov:</p>
<pre>>>> s.ljust(15)
'Benjamin '
>>> s.rjust(15)
' Benjamin'
>>> s.center(15)
' Benjamin '</pre>
<p>(Še enkrat: te metode ne spreminjajo niza, temveč vrnejo nov niz!)</p>
<p>Metoda <code>strip</code> naredi ravno nasprotno: odbije presledke (in
tabulatorje in znake za prehod v novo vrstico) na levi in desni strani
niza. <code>lstrip</code> in <code>rstrip</code> pospravita samo levo in
samo desno stran.</p>
<pre>>>> s = ' asdf '
>>> s.lstrip()
'asdf '
>>> s.rstrip()
' asdf'
>>> s.strip()
'asdf'</pre>
<p>Če se zdi ta metoda komu neuporabna, se moti. Zelo.</p>
<p>Nizi imajo še veliko metod. Pogledali bomo le še dve najzanimivejši.</p>
<p>Metoda <code>split</code> razbije niz na seznam podnizov, kakor jih ločujejo
presledki, tabulatorji in znaki za nove vrstice. (V prvem približku:
razbije jih na besede.)</p>
<pre>>>> s = 'Metoda split razbije niz na seznam podnizov, kakor jih ločujejo presledki.'
>>> s.split()
['Metoda', 'split', 'razbije', 'niz', 'na', 'seznam', 'podnizov,', 'kakor', 'jih', 'locujejo', 'presledki.']</pre>
<p>Presledkom, tabulatorjem in znakom za novo vrstico rečemo tudi <em>beli
prostor</em> (<em>white space</em>). Namesto glede na beli prostor lahko
<code>split</code> razbije niz tudi glede na kak drug znak, ki ga moramo
v tem primeru podati kot argument.</p>
<pre>>>> "123-4123-21".split("-")
['123', '4123', '21']
>>> "123-4123-21".split("1")
['', '23-4', '23-2', '']</pre>
<p>Zadnja metoda, <code>join</code>, dela ravno obratno kot <code>split</code>:
združuje nize. Način, na katerega je obrnjena, je nenavaden, a če malo
razmislimo, vidimo, da drugače ne bi moglo biti.</p>
<pre>>>> imena = ["Ana", "Berta", "Cilka", "Dani", "Ema"]
>>> "".join(imena)
'AnaBertaCilkaDaniEma'</pre>
<p>Praznemu nizu, "", smo "naročili", naj združi nize iz podanega seznama. To
sicer ni videti preveč lepo, lepše bo, če jih združimo s kakim ločilom.</p>
<pre>>>> "-".join(imena)
'Ana-Berta-Cilka-Dani-Ema'
>>> ", ".join(imena)
'Ana, Berta, Cilka, Dani, Ema'
>>> "--".join(imena)
'Ana--Berta--Cilka--Dani--Ema'
>>> " in ".join(imena)
'Ana in Berta in Cilka in Dani in Ema'</pre>
<p>Najlepše pa bo, če zadnjo vejico zamenjamo z "in".
<pre>>>> ", ".join(imena[:-1]) + " in " + imena[-1]
'Ana, Berta, Cilka, Dani in Ema'</pre>
<p>Tule smo z <code>join</code> združili vse elemente razen zadnjega. K temu
nizu smo prišteli niz " in " in še zadnje ime s seznama.</p>
<h2>Metode seznamov</h2>
<p>Tako kot nizi imajo tudi seznami metodi <code>count</code> in
<code>index</code>, o katerih ne bomo izgubljali besed.</p>
<p>Omenili smo že <code>append</code>, ki v seznam doda nov element. Pazite,
tole je pa zelo drugače kot pri nizih! Metoda <code>append</code> ne vrača
novega seznama, temveč v resnici spreminja seznam.</p>
<p>Kako pa bi k nizu pripeli seznam? Tule nam <code>append</code> ne bo
pomagal: kar naredi, je povsem narobe.</p>
<pre>>>> imena
['Ana', 'Berta', 'Cilka', 'Dani', 'Ema', 'Fanci', ['Greta', 'Hilda']]</pre>
<p>Kaj smo pa pričakovali? Metoda <code>append</code> doda k seznamu nov
element. Kar ji podamo kot argument, bo zadnji element seznama. Če torej
<code>append</code>u podamo seznam, bo seznam zadnji element seznama.</p>
<p>Uporabiti moramo metodo <code>extend</code>.</p>
<pre>>>> imena = ['Ana', 'Berta', 'Cilka', 'Dani', 'Ema', 'Fanci']
>>> imena.extend(["Greta", "Hilda"])
>>> imena
['Ana', 'Berta', 'Cilka', 'Dani', 'Ema', 'Fanci', 'Greta', 'Hilda']</pre>
<p>Mimogrede, isto bi dosegli tudi z</p>
<pre>imena += ["Greta", "Hilda"]</pre>
<p>Metode <code>extend</code> praktično ne uporabljamo, ker je nepotrebna.</p>
<p>Metodi <code>insert</code> podamo dva argumenta, indeks in element, pa bo
vstavila element <em>pred</em> element s podanim indeksom (to si zapomnimo
takole: argument, ki ga podamo, bo indeks novega elementa).</p>
<pre>>>> imena = ['Ana', 'Berta', 'Cilka', 'Dani', 'Ema', 'Fanci']
>>> imena.insert(2, "PredCilka")
>>> imena.insert(-2, "PreEma")
>>> imena
['Ana', 'Berta', 'PredCilka', 'Cilka', 'Dani', 'PreEma', 'Ema', 'Fanci']</pre>
<p>Očitno deluje tudi indeksiranje s konca.</p>
<p>Elemente seznama lahko odstranjujemo na tri načine. Prvega smo spoznali že
prejšnjič: z ukazom <code>del</code>. Še enkrat: <code>del</code> ni metoda
in prihaja iz povsem drugega vica, a vseeno ga pač omenimo, ker sodi
sem.</p>
<pre>>>> imena
['Ana', 'Berta', 'PredCilka', 'Cilka', 'Dani', 'PreEma', 'Ema', 'Fanci']
>>> del imena[2]
>>> imena
['Ana', 'Berta', 'Cilka', 'Dani', 'PreEma', 'Ema', 'Fanci']</pre>
<p>Metoda <code>pop</code> vrne element s podanim indeksom in ga pobriše s
seznama.</p>
<pre>>>> ime = imena.pop(2)
>>> ime
'Cilka'
>>> imena
['Ana', 'Berta', 'Dani', 'PreEma', 'Ema', 'Fanci']</pre>
<p>Priznati moram, da metode <code>pop</code> nisem še nikoli uporabil na ta
način - vsaj ne da bi se tega spomnil. V resnici namreč vedno pobiramo
elemente z začetka ali s konca seznama. Metodo <code>pop</code> lahko zato
pokličemo tudi brez argumentov: v tem primeru vrača zadnji element.</p>
<pre>>>> imena
['Ana', 'Berta', 'Dani', 'PreEma', 'Ema', 'Fanci']
>>> imena.pop()
'Fanci'
>>> imena.pop(0)
'Ana'
>>> imena
['Berta', 'Dani', 'PreEma', 'Ema']</pre>
<p>Če bi hoteli, recimo, prestaviti prvi element na konec, bi napisali
<code>imena.append(imena.pop(0))</code>.</p>
<p>Tretji način je, da elementa, ki ga želimo odstraniti, ne določimo z
indeksom, temveč z vrednostjo - povemo, kakšen element bi radi odstranili.
Temu je namenjena metoda <code>remove</code>.</p>
<pre>>>> imena.remove("Dani")
>>> imena
['Berta', 'PreEma', 'Ema']</pre>
<p>Pri tem ne odstrani vseh takšnih elementov, temveč le prvega, na katerega
naleti, kakor lahko vidimo v spodnjem primeru.</p>
<pre>>>> s = [7, 1, 2, 3, 4, 1, 1, 2]
>>> s.remove(1)
>>> s
[7, 2, 3, 4, 1, 1, 2]</pre>
<p>Metoda <code>s.copy()</code> naredi kopijo seznama <code>s</code>, tako
kot da bi napisali <code>s = s[:]</code>.</p>
<p>Metoda <code>s.clear()</code> ga
izprazni, kar je isto kot <code>s[:] = []</code> in <em>ni isto kot</em>
<code>s = []</code>. Razlika je tako prefinjena, da bo vredna posebnega
predavanja.</p>
<p>Le še dve metodi sta nam ostali. <code>reverse</code> obrne vrstni red
elementov v seznamu.</p>
<pre>
[7, 2, 3, 4, 1, 1, 2]
>>> s.reverse()
>>> s
[2, 1, 1, 4, 3, 2, 7]</pre>
<p>Zadnja je <code>sort</code>, ki uredi elemente po vrsti.</p>
<pre>>>> s.sort()
>>> s
[1, 1, 2, 2, 3, 4, 7]</pre>
<p>Metoda deluje nad vsakršnimi elementi, ki jih je mogoče primerjati - z njo
lahko uredimo seznam števil, nizov... Podamo ji lahko tudi kup argumentov,
ki pa jih v tem trenutku še nismo zmožni razumeti.</p>
<p>Ne spreglejte razlike med metodami nizov in seznamov. Metode nizov vračajo
nove nize; <code>s.replace("min", "max")</code> ni spremenil niza
<code>s</code>, temveč vrnil nov niz. Metode seznamov spreminjajo seznam;
<code>s.insert(2, "Ana")</code> ne vrne novega seznama, temveč spremeni
<code>s</code>.</p>
<h2>Metode terk</h2>
<p>Terke imajo enake metode kot seznami, manjkajo jim le metode, ki spreminjajo
seznam. Teh pa, roko na srce, ni veliko. ;) Terke imajo le dve metodi:
<code>count</code> in <code>index</code>.</p>
</body>
</html>
|