summaryrefslogtreecommitdiff
path: root/python/problems/lists_and_for/list_for_sl.html
blob: ae5b385216191cdf479d33fcfff1b39c53a3f1d5 (plain)
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
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
<!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>

<h2>Seznami</h2>

<p>Recimo, da smo zbrali teže šestih študentov. Seznam tež zapišemo takole:</p>

<pre>teze = [74, 82, 58, 66, 61, 84]</pre>

<p>Seznam (angl. <em>list</em>)
    je zaporedje česarkoli, recimo števil, lahko pa tudi česa drugega. Števila
    ali kaj drugega naštejemo, vmes pišemo vejice in vse skupaj zapremo v
    oglate oklepaje <code>[</code> in <code>]</code>. Za primer sestavimo še
    seznam imen študentov:</p>

<pre>imena = ["Anze", "Benjamin", "Cilka", "Dani", "Eva", "Franc"]</pre>

<p>in seznam, ki bo povedal, ali gre za študenta ali študentko</p>

<pre>studentka = [False, False, True, False, True, False]</pre>

<p>Seznami lahko vsebujejo tudi še hujšo eksotiko. Imamo lahko, recimo, seznam
    seznamov - vanj bomo, prikladno, stlačili (pod)sezname teža-ime-spol:</p>

<pre>podatki = [
    [74, "Anze", False],
    [82, "Benjamin", False],
    [58, "Cilka", True],
    [66, "Dani", False],
    [61, "Eva", True],
    [84, "Franc", False],
    ]</pre>

<p>To sicer navadno delamo malo drugače (pogosto celo precej drugače), a dokler
    tega še ne znamo, bo dobro tudi tako. Mimogrede opazimo še dve stvari:
    seznam lahko, če želimo, raztegnemo v več vrst, preprosto tako, da ne
    zapremo oklepaja. Naredili bi lahko tudi tole</p>

<pre>teze = [74, 82, 58,
        66, 61, 84]</pre>

<p>Seznami lahko vsebujejo tudi še hujšo hujšo eksotiko. V resnici lahko
    vsebujejo karkoli, celo, recimo, funkcije:</p>

<pre>from math import *

par_funkcij = [sin, cos, radians]</pre>

<p>Čemu bi kdo hotel narediti seznam funkcij?! I, zato da jih bo klical,
    seveda. Pa kdaj kdo kliče funkcije s seznama?! Da, včasih pride prav.</p>

<p>Nikjer tudi ne piše, da morajo biti vsi elementi seznama istega tipa. To smo
    pravzaprav že izkoristili: podseznami s težo, imenom in spolom so vsebovali
    število, niz in logično vrednost. Navrgli bi lahko še dve funkciji in en
    seznam; pa ne bomo, to se ne dela. Če želimo sezname različnih tipov,
    raje uporabimo terke. Kaj so terke, bomo izvedeli vsak čas.)</p>

<p>Seznam je lahko tudi prazen</p>

<pre>prazen = []</pre>

<p>ali pa ima en sam element</p>

<pre>samo_edini = [42]</pre>

<p>Ali pa je poln praznih seznamov</p>

<pre>polnoprazen = [[], [], [], [], [], []]</pre>



<h2>Terka</h2>

<p>Terka (angl. <em>tuple</em>) je podobna seznamu. Kakšna je pomembna razlika,
    bomo še videli, manj pomembna pa je ta, da pri terki namesto oglatih
    oklepajev uporabljamo kar okrogle. (Skoraj) vse ostalo ostane enako:</p>

<pre>teze = (74, 82, 58, 66, 61, 84)
imena = ("Anze", "Benjamin", "Cilka", "Dani", "Eva", "Franc")</pre>

<p>Pri terkah se nam - zaradi tega, kje in kako jih uporabljamo, pogosteje
    zgodi, da vsebuje elemente različnih tipov. Recimo takole:</p>

<pre>student = (74, "Anze", False)</pre>

<p>Tudi seznam teža-ime-spol bi raje naredil takole:</p>

<pre>podatki = [
    (74, "Anze", False),
    (82, "Benjamin", False),
    (58, "Cilka", True),
    (66, "Dani", False),
    (61, "Eva", True),
    (84, "Franc", False),
    ]</pre>

<p>Tako kot seznami so tudi terke lahko prazne (<code>()</code>) ali pa imajo
    po en sam element. Tu imamo težavo pri terki z enim samim elementom: Če bi
    napisali <code>(42)</code> to ni seznam, temveč le 42 v oklepaju (odvečnem,
    seveda). Da bi povedali, da gre za terko, moramo dodati še vejico:</p>

<pre>samo_en = (42, )</pre>

<p>Terko smemo, zanimivo, pisati tudi brez oklepajev.</p>

<pre>>>> t = 1, 2, 3, 4
>>> t
(1, 2, 3, 4)</pre>

<p>Ker to ni preveč pregledno, pa to počnemo le v posebnih primerih, na katere
bomo sproti opozorili.</p>


<h3>Razpakiranje v elemente</h3>

<p>Včasih imamo seznam ali terko z nekaj elementi, ki bi jih radi priredili
    več spremenljivkam. Recimo, da imamo</p>

<pre>student = (74, "Anze", False)</pre>

<p>Če želimo podatke prirediti spremenljivkam <code>teza</code>,
    <code>ime</code> in <code>je_zenska</code>, bi to lahko storili takole:</p>

<pre>>>> teza, ime, je_zenska = student</pre>

<p>Doslej smo imeli pri prirejanju na levi strani vedno eno samo spremenljivko,
    ki smo ji želeli prirediti vrednost na desni strani enačaja. Tu pa smo na
    levi našteli več imen spremenljivk (tri), na desni pa mora biti za to terka
    z enakim številom elementov (tremi). Terka? No, lahko je tudi seznam ali
    niz.</p>

<pre>>>> a, b, c = [1, 2, 3]
>>> a
1
>>> a, b, c = "xyz"
>>> a
'x'
>>> b
'y'
>>> c
'z'</pre>

<p>Več ko boste programirali v Pythonu, bolj boste čutili moč terk. Omenimo,
recimo, da je z njimi mogoče napisati funkcijo, ki ne vrača ene, temveč več
stvari. Vzemimo funkcijo <code>splitext</code>, ki ji damo ime datoteke,
pa vrne njeno osnovno ime in njeno končnico.</p>

<pre>>>> from os.path import *
>>> film = "Babylon 5 - 3x04 - Passing through Gethsemane.avi"
>>> zac, konc = splitext(film)
>>> zac
'Babylon 5 - 3x04 - Passing through Gethsemane'
>>> konc
'.avi'</pre>

<p>V resnici funkcija <code>splitext</code> vrne terko,</p>

<pre>>>> from os.path import *
>>> splitext(film)
('Babylon 5 - 3x04 - Passing through Gethsemane', '.avi')</pre>

<p>ki pa smo jo kar mimogrede razpakirali v <code>zac</code> in
    <code>konc</code>.</p>

<p>Seveda bi lahko rezultat funkcije priredili tudi eni sami spremenljivki -
    v tem primeru bi bila ta spremenljivka terka.</p>

<pre>>>> t = splitext(film)
>>> t
('Babylon 5 - 3x04 - Passing through Gethsemane', '.avi')</pre>

<p>In seveda bi lahko terko nato še razpakirali.</p>

<pre>ime, koncnica = t</pre>

<p>Kako v Pythonu zamenjamo vrednosti dveh spremenljivk?</p>

<pre>a = "Alenka"
b = "Tina"</pre>

<p>Želeli bi, da bi <code>a</code> postal "Tina" in <code>b</code> "Alenka".
    Naivnež bi napisal tale nesmisel:</p>

<pre>a = b
b = a</pre>

<p>To seveda ne deluje. V prvi vrstici <code>a</code>-ju priredimo
    <code>b</code>, se pravi, "Tina", v drugi vrstici pa <code>b</code>-ju
    <code>a</code>, ki pa je medtem postal "Tina". Tako sta po tem
    <code>a</code> in <code>b</code> enaka "Tina".</p>

<p>V drugih jezikih se navadno rešimo tako, da vrednost <code>a</code>-ja
    spravimo na varno, preden ga povozimo.</p>

<pre>tmp = a
a = b
b = tmp</pre>

<p>V Pythonu pa to ni potrebno. Spremenljivki preprosto zapakiramo v terko, ki
    jo takoj razpakiramo nazaj, a v obratnem vrstnem redu.</p>

<pre>a, b = (b, a)</pre>

<p>V resnici navadno ne pišemo tako, temveč izpustimo oklepaje.</p>

<pre>a, b = b, a</pre>

<p>Oklepaje okrog terke izpuščamo preprosto zato, ker je takšno prirejanje
    tako pogosto, da ga programer vajen Pythona takoj prepozna. Pri tem tudi
    ne razmišljamo o terkah, temveč prirejanje preberemo preprosto tako, da
    <code>a</code>-ju priredimo <code>b</code> in <code>b</code>-ju
    <code>a</code>.</p>


<h2>Zanka for</h2>

<p>Python ima dve vrsti zank: zanki <code>while</code>, ki jo že poznamo, dela
    družbo <code>for</code>.</p>

<p>Zastavimo si preprosto nalogo (in ne čisto smiselno) nalogo: izpišimo teže
    in kvadrate tež vseh študentov v seznamu. Se pravi (po slovensko):</p>

<pre>za vsako težo s seznama teze stori tole:
    izpiši težo in težo na kvadrat</pre>

<p>V Pythonu pa prav tako, samo brez sklonov:</p>
<pre>for teza in teze:
    print(teza, teza ** 2)</pre>

<p>V zanki <code>for</code> se skriva prirejanje. Zanka najprej
    <em>priredi</em> spremenljivki <code>teza</code> prvi element seznama
    <code>teze</code>. Nato se izvrši vsa koda bloka znotraj bloka
    <code>for</code> - tako, kot se je dogajalo v zanki <code>while</code>.
    V naslednji rundi priredi spremenljivki <code>teza</code> drugi element in
    spet izvede kodo znotraj bloka, ... ter tako naprej do konca seznama.</p>

<p>Zdaj pa izpišimo vse teže, ki so večje od 70.</p>

<pre>for teza in teze:
    if teza > 70:
        print(teza)</pre>

<p>Napišimo program, ki pove, kako težak je najlažji študent.</p>

<pre>najlazji = 1000
for teza in teze:
    if teza < najlazji:
        najlazji = teza
print(najlazji)</pre>

<p>Je potrebno prevesti v slovenščino? Pa dajmo.</p>

<pre>za začetek naj bo najlažja teža 1000 (gotovo bomo kasneje našli koga lažjega)
za vsako težo iz seznama tež:
    če je teža manjša od najmanjše doslej:
        najlažja je ta teža
izpiši najmanjšo težo</pre>

<p>Deluje ta program samo na seznamih števil? Ali pa bi znal poiskati tudi
   najmanjši niz? Kako pravzaprav primerjamo nize? Nize primerja, seveda, po
   abecedi. In, da, program deluje tudi na nizih, vrne "najmanjši" niz - prvi
   niz po abecedi. Le v začetku moramo napisati
   <code>najlazji = "ŽŽŽŽŽŽŽŽŽŽŽŽ"</code> namesto <code>najlazji = 1000</code>.
   (Tole se da sprogramirati tudi tako, da deluje za nize in za števila. A ne
   bomo ubijali začetnikov s prezapletenimi programi.)</p>

<p>Mimogrede, Python ima že vdelano funkcijo <code>min</code>, ki vrne
   najmanjši element seznama.</p>

<p>Kako bi izračunali vsoto elementov seznama?</p>

<pre>s = 0
for teza in teze:
    s += teza</pre>

<p>Pa poprečno vrednost? Za to moramo poznati dolžino seznama. Pove nam jo
funkcija <code>len</code> (okrajšava za <em>length</em>, če ji kot argument
podamo nek seznam).</p>

<pre>s = 0
for teza in teze:
    s += teza
s /= len(teze)</pre>

<p>Samo... malo previdni moramo biti. Seznam bi lahko bil tudi prazen.
   Dogovorimo se, da bo poprečna vrednost v tem primeru 0. Pravilno delujoč
   program bi bil takšen.</p>

<pre>s = 0
for teza in teze:
    s += teza
if len(teze) > 0:
    s /= len(teze)</pre>

<p>Zanka for ne deluje le na seznamih. Tako, kot gre prek seznamov, lahko
    gre tudi prek terk, nizov in še prek mnogih drugih reči. V Pythonu celo za
    branje datotek pogosto uporabimo <code>for</code>, kot se bomo kmalu
    naučili.</p>

<pre>>>> ime = "Cilka"
>>> for crka in ime:
...     print(crka)
'C'
'i'
'l'
'k'
'a'</pre>


<h2>Najdi takšnega, ki...</h2>

<p>Kako bi ugotovili, ali vsebuje seznam kako sodo število?</p>

<pre>s = [11, 13, 5, 12, 5, 16, 7]

imamo_sodo = False
for e in s:
    if e % 2 == 0:
        imamo_sodo = True
if imamo_sodo:
    print("Seznam vsebuje sodo število")
else:
    print("Seznam ne vsebuje sodega števila")</pre>

<p>V začetku si rečemo, da nimamo nobenega sodega števila. Nato gremo prek
vseh števil in čim naletimo na kakega sodega, zabeležimo, da smo, aleluja,
našli sodo število.</p>

<p>Ne naredite klasične napake. Tole je narobe:</p>

<pre>s = [11, 13, 5, 12, 5, 16, 7]

imamo_sodo = False
for e in s:
    if e % 2 == 0:
        imamo_sodo = True
    else:
        imamo_sodo = False
if imamo_sodo:
    print("Seznam vsebuje sodo število")
else:
    print("Seznam ne vsebuje sodega števila")</pre>

<p>Ta program se bo ob vsakem lihem številu delal, da doslej ni bilo še
nobenega sodega - zaradi <code>imamo_sodo = False</code> bo pozabil, da je
kdajkoli videl kako sodo število. V gornjem seznamu bo, recimo, pregledal
vsa števila, končal bo s 7 in si ob tem rekel <code>imamo_sodo = False</code>.
Rezultat bo tako napačen.</p>

<p>Kako pa ugotovimo, ali ima seznam <em>sama soda števila</em>?</p>

<pre>sama_soda = True
for e in s:
    if e % 2 != 0:
        sama_soda = False
if sama_soda:
    print("Seznam vsebuje sama soda število")
else:
    print("Seznam ne vsebuje samo sodih števil")</pre>

<p>Spet bomo naredili podobno napako kot prej, če bomo pisali:</p>

<pre>s = [11, 13, 5, 12, 5, 16, 72]

sama_soda = True
for e in s:
    if e % 2 != 0:
        sama_soda = False
    else:
        sama_soda = True</pre>

<p>Program že takoj, ko vidi 1, ugotovi, da niso vsa števila v seznamu soda,
in postavi <code>sama_soda = False</code>. Vendar melje seznam naprej in ob
vsakem koraku znova nastavlja <code>sama_soda</code>. Ko pride do 72, postavi
<code>sama_soda</code> na <code>True</code>. To pa je ravno zadnje število;
<code>sama_soda</code> ostane <code>True</code>... pa smo tam.</p>



<h2>Prekinjanje zank</h2>

<p>Ko smo prejšnji teden pisali zanko <code>while</code>, smo postavili pogoj,
    do kdaj naj se izvaja. Zanka for bo, če se vmes ne pripeti kaj posebnega,
    šla vedno od začetka do konca seznama (terke, niza, datoteke...)</p>

<p>Včasih to ni potrebno. Pravzaprav smo pravkar videli takšen primer:
   rezultat gornjega programa je znan že, čim naletimo na prvo liho
   število. Torej bi bilo čisto vseeno, če računalnik v tistem trenutku neha
   pregledovanje. To mu v resnici lahko naročimo.</p>

<pre>sama_soda = True
for e in s:
    if e % 2 != 0:
        sama_soda = False
        break
if sama_soda:
    print("Seznam vsebuje sama soda število")
else:
    print("Seznam ne vsebuje samo sodih števil")</pre>

<p>Ukaz <code>break</code> pomeni, da želimo prekiniti zanko. Program skoči
"ven" iz zanke in nadaljuje z izvajanjem ukazov, ki sledijo zanki.</p>

<p>Mimogrede, na podoben način lahko prekinemo tudi <code>while</code>.</p>

<p>Tule je bil <code>break</code> skoraj bolj zaradi lepšega - da računalnik
ne izgublja časa brez potrebe. Poskusimo napisati program, ki takrat, ko seznam
ni vseboval samo sodih števil, izpiše prvo liho število.</p>

<pre>sama_soda = True
for e in s:
    if e % 2 != 0:
        sama_soda = False
        liho = e
if sama_soda:
    print("Seznam vsebuje samo soda števila")
else:
    print("Seznam ne vsebuje samo sodih števil: prvo liho število je", liho)</pre>

<p>Brez <code>break</code> tole ne deluje: namesto prvega izpiše zadnje liho
število. Rešimo se lahko z dodatnim pogojem:</p>

<pre>sama_soda = True
for e in s:
    if e % 2 != 0 and sama_soda:
        sama_soda = False
        liho = e
if sama_soda:
    print("Seznam vsebuje samo soda števila")
else:
    print("Seznam ne vsebuje samo sodih števil: prvo liho število je", liho)</pre>

<p>S tem, ko smo dodali <code>and sama_soda</code> smo poskrbeli, da se bosta
<code>sama_soda = False</code> in <code>liho = e</code> izvedla le prvič. Ko
bomo postavili <code>sama_soda</code> na <code>False</code>, bomo dosegli, da
pogoj ne bo nikoli nikoli več resničen.</p>

<p>Namesto dodatnega pogoja lahko napišemo <code>break</code>.</p>

<pre>sama_soda = True
for e in s:
    if e % 2 != 0 and sama_soda:
        sama_soda = False
        liho = e
        break
if sama_soda:
    print("Seznam vsebuje samo soda števila")
else:
    print("Seznam ne vsebuje samo sodih števil: prvo liho število je", liho)</pre>

<p>S tem se program lahko pravzaprav še bolj poenostavi. Ko zanko prekinemo,
<code>e</code> ostane, kar je bil. Torej ne potrebujemo več spremenljivke
<code>liho</code>.</p>

<pre>sama_soda = True
for e in s:
    if e % 2 != 0:
        sama_soda = False
        break
if sama_soda:
    print("Seznam vsebuje samo soda števila")
else:
    print("Seznam ne vsebuje samo sodih števil: prvo liho število je", e)</pre>

<h2>Else po zanki</h2>

<p>Medtem, ko je ukaz <code>break</code> zelo običajna žival v vseh
    programskih jezikih, ima Python še eno posebnost, povezano z zankami. V
    večini programskih jezikov lahko <code>else</code> uporabimo kot "odgovor"
    na <code>if</code>. V Pythonu pa lahko <code>else</code> sledi tudi zanki
    <code>for</code> ali <code>while</code>. V pogojnem stavku (<code>if</code>)
    se koda v <code>else</code> izvede, če pogoj ni bil resničen. Po zanki se
    <code>else</code> izvede, če se zanka <em>ni prekinila</em> zaradi
    <code>break</code>. Torej, <code>else</code> se izvede pri zankah, ki so
    se iztekle "po naravni poti".</p>

<p>Oglejmo si še enkrat gornji program. Kar smo počeli v njem, je kar pogosto:
    v zanki nekaj iščemo (recimo kako liho število). Če to reč najdemo, nekaj
    storimo (ga izpišemo) in prekinemo zanko. Sicer (torej, če ga ne najdemo),
    storimo kaj drugega (izpišemo, da ga nismo našli).</p>

<p>Zgornji odstavek se približno, a ne čisto povsem prilega zadnjemu kosu
programa. V resnici je napisan po spodnjem programu:</p>

<pre>for e in s:
    if e % 2 != 0:
        print("Seznam ne vsebuje samo sodih števil: prvo liho število je", e)
        break
else:
    print("Seznam vsebuje samo soda števila")</pre>

<p>Se pravi: če najdemo liho število, napišemo, da seznam vsebuje liho število
in prekinemo zanko. Ta del je jasen. Ne spreglejte pa, kje je <code>else</code>:
poravnan je s <code>for</code> ne z <code>if</code>! Ta <code>else</code>
se torej nanaša na <code>for</code>. Kar napišemo v <code>else</code>-u za
<code>for</code>, se zgodi, če se zanka ni prekinila z <code>break</code>om.</p>

<p>Preden naredimo še kakšen primer, si oglejmo še nekaj drugega.</p>


<h2>Štetje z zanko <code>for</code></h2>

<div style="font-size: 80%">
<p>Tisti, ki poznajo kak drug, C-ju podoben jezik, so najbrž pričakovali
    <a href="http://en.wikipedia.org/wiki/For_loop#Kinds_of_for_loops">nekoliko
    drugačno zanko</a>.</p>

<p>Poglejmo resnici v oči: v C, C++, C#, Javi sta zanka for in while le dva
načina, na katera povemo eno in isto.</p>

<pre>for(zacetek; pogoj; korak) {
    koda;
}</pre>

<p>je isto kot</p>

<pre>zacetek;
while(pogoj) {
    koda;
    korak;
}</pre>

<p>Če je ideja zanke for v C-ju podobnih jezikih ta, da se z njo šteje, pa
    imamo v Pythonu za to nekaj priročnejšega in splošnejšega.</p>
</div>

<p>V programih pogosto potrebujemo še dva tipa zank. Pogosto bomo želeli nekaj
ponoviti vnaprej predpisano oziroma pred zanko izračunano število ponovitev, recimo
petkrat ali desetkrat. Prav tako bomo pogosto želeli, da program "šteje" od
10 do 20, od 0 do 100 ali kaj takega.</p>

<p>Za oboje bo poskrbela kar zanka for, ob pomoči priročne funkcije
    <code>range</code>.</p>

<p>Funkcija <code>range</code> je na prvi pogled povsem neimpresivna. Vrača
   sezname zaporednih števil.</p>

<p>V Pythonu 3.0 je ta funkcija narejena boljše kot v različicah pred njim,
    vendar je nova oblika za začetnika manj očitna, zato bomo za trenutek
    skočili v stari Python 2.7. Kar sledi, v novem Pythonu namreč ne bi dalo
    enakih izpisov.</p>

<pre>>>> range(5, 10)
[5, 6, 7, 8, 9]
>>> range(10, 20)
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> range(7)
[0, 1, 2, 3, 4, 5, 6]
>>> range(16)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]</pre>

<p>Funkcija <code>range</code> je vrnila seznam celih števil, ki se začne pri
    prvi vrednosti in konča eno pred zadnjo. Koliko elementov ima seznam,
    ki ga vrne <code>range(7)</code>? Sedem. Zato
   ker vsebuje prvi element in ne zadnjega, in ker se začne z 0.</p>

<p>Funkcija <code>range</code> je torej narejena praktično, ker se težko zmotimo
glede tega, koliko elementov bo vrnila.</p>

<p>Lepo se tudi sešteva. <code>range(10, 15) + range(15, 20)</code> so ravno
vsa števila od 10 do 20. Če bi bil <code>range(10, 15)</code> enak
<code>[10, 11, 12, 13, 14, 15]</code>, bi se v
<code>range(10, 15) + range(15, 20)</code> število 15 ponovilo dvakrat.</p>

<p>Funkcija ima lahko še en, tretji argument. Ta predstavlja korak.</p>

<pre>>>> range(5, 15, 2)
[5, 7, 9, 11, 13]</pre>

<p>Korak je lahko tudi negativen.</p>

<pre>>>> range(10, 0, -1)
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> range(10, 0, -3)
[10, 7, 4, 1]
>>> range(10, 0, -5)
[10, 5]</pre>

<p>Funkcijo <code>range</code> uporabljamo skoraj izključno v zankah
    <code>for</code>.</p>

<p>V prvi zanki <code>while</code>, ki smo jo napisali, smo izpisali števila
od 1 do 10, takole nekako:</p>

<pre>i = 1
while i < 11:
    print(i)
    i += 1</pre>

<p>Z zanko <code>for</code> je preprostejši.</p>

<pre>for i in range(1, 11):
    print(i)</pre>

<p>Seveda ostaja odprto vprašanje, zakaj bi si kdo tako želel izpisati števila
od 1 do 10. Štetje je kljub temu uporabno tudi za kaj drugega, ne le za
izpisovanje.
</p>

<h3>Praštevila</h3>

<p>Napisati želimo program, ki pove, ali je dano število praštevilo. Za to bomo
    preverili vsa števila od 2 do n-1: če katerokoli od njih deli
    <code>n</code>, potem <code>n</code> ni praštevilo.</p>

<pre>n = int(input("Vpiši število"))
je_prastevilo = True
for i in range(2, n):
    if n % i == 0:
        je_prastevilo = False</pre>

<p>V začetku predpostavimo, da je število praštevilo
    (<code>je_prastevilo = True</code>), če med števili med 2 in n
    (<code>for i in range(2, n)</code>) naletimo na njegov delitelj
    (<code>if n % i == 0</code>), pa presodimo, da število pač ne more biti
    praštevilo (<code>je_prastevilo = False</code>). Mimogrede naj opozorimo
    na napako, na katero stalno opozarjamo:</p>

<pre>n = int(input("Vpiši število"))
je_prastevilo = True
for i in range(2, n):
    if n % i == 0:
        je_prastevilo = False
    else:
        je_prastevilo = True # TO JE NAROBE!</pre>

<p>Ko je število enkrat obsojeno kot sestavljeno, ga ne moremo več "pomilostiti"
    nazaj v praštevilo. Če je tako, pa tudi ni potrebe, da bi po tem, ko enkrat
    odkrijemo delitelj, sploh še preverjali naslednje potencialne delitelje.
    Zdaj pač že vemo: <code>break</code> in <code>else</code> po zanki.

<pre>n = int(input("Vpiši število"))

for i in range(2, n):
    if n % i == 0:
        print(n, "ni praštevilo, saj je deljivo z", i)
        break
else:
    print(n, "je praštevilo")</pre>

<h2>Razpakiranje v zanki <code>for</code>code> in še malo telovadbe</h2>

<p>Nekoč na začetku predavanja smo imeli seznam študentov in njihovih tež:</p>

<pre>podatki = [
    (74, "Anze", False),
    (82, "Benjamin", False),
    (58, "Cilka", True),
    (66, "Dani", False),
    (61, "Eva", True),
    (84, "Franc", False),
    ]</pre>

<p>Recimo, da bi radi izpisali imean študentov in njihove teže.</p>

<p>Če gremo prek seznama z zanko <code>for</code>, bomo dobivali terke. Te
lahko, vemo, razpakiramo.</p>

<pre>for student in podatki:
    teza, ime, spol = student
    print(ime, ": ", teza)</pre>

<p>Gre pa še dosti elegantneje: razpakiranje lahko opravimo kar znotraj
glave zanke, brez (nepotrebne) terke <code>t</code>:</p>

<pre>for teza, ime, je_zenska in podatki:
    print(ime, ": ", teza)</pre>

<p>Program torej pravi</p>

<pre>za vsako trojko (teza, ime, je_zenska) iz seznama podatki:
    izpisi ime in tezo</pre>

<p>Lahko pa se tudi malo igramo in izrišemo graf:</p>

<pre>for teza, ime, je_zenska in podatki:
    print(ime + " " + "*"*teza)</pre>

<p>Skoraj, ampak ne čisto. Vse skupaj bi radi še poravnali. O tem, kako se v
    resnici oblikuje izpis, se bomo pogovarjali drugič, danes pa bomo s tem
    opravili nekoliko po domače.
    Predpostavimo, da so imena dolga največ 15 znakov. Pred vsako ime bomo
    dopisali toliko presledkov, da bo skupna dolžina enaka 15. (Mimogrede
    bom izdal, da dolžino niza dobimo s funkcijo <code>len</code>.)</p>

<pre>for teza, ime, je_zenska in podatki:
    print(" "*(15 - len(ime)) + ime + " " + "*"*teza)</pre>


<h2>Zanka po dveh seznamih</h2>

<p>Zdaj pa izpišimo imena in teže, pri tem, da se le-ta nahajajo v ločenih
    seznamih.</p>

<pre>teze = [74, 82, 58, 66, 61, 84]
imena = ["Anze", "Benjamin", "Cilka", "Dani", "Eva", "Franc"]
studentka = [False, False, True, False, True, False]</pre>

<p>Naivno bi se lotili takole</p>

<pre>
for ime in imena:
    print(ime, ":")
</pre>

<p>in potem obstali, ker na tem mestu ne moremo priti do teže študenta s tem
    imenom. Do običajne in zelo zelo zelo napačne rešitve nas pripelje ta
    zgrešeni premislek: zanko moramo speljati prek imen in prek tež, torej</p>

<pre>
for ime in imena:
    for teza in teze:
        print(ime, ": ", teza)
</pre>

<p>Rezultat je nepričakovan za vse tiste, ki ga niso pričakovali. Program
    namreč izpiše</p>

<pre>Anze :  74
Anze :  82
Anze :  58
Anze :  66
Anze :  61
Anze :  84
Benjamin :  74
Benjamin :  82
Benjamin :  58
Benjamin :  66
Benjamin :  61
Benjamin :  84
Cilka :  74
Cilka :  82
Cilka :  58
Cilka :  66
Cilka :  61
Cilka :  84
Daniel :  74
Daniel :  82
Daniel :  58
Daniel :  66
Daniel :  61
Daniel :  84
Eva :  74
Eva :  82
Eva :  58
Eva :  66
Eva :  61
Eva :  84
Franc :  74
Franc :  82
Franc :  58
Franc :  66
Franc :  61
Franc :  84
</pre>

<p>Računalniki imajo to nadležno navado, da vedno naredijo natanko
    tisto, kar jim naročimo. In v tem primeru smo mu naročili tole:</p>

<pre>
za vsako ime na seznamu ime stori tole:
    za vsako tezo na seznamu tez stori tole:
        izpisi ime in tezo</pre>

<p>Kdor ne razume, kaj se je zgodilo in zakaj, naj to nujno premisli, da se ne
bo kasneje učil na lastnih napakah.</p>

<p>Ko bo to opravljeno, bo razumel: potrebujemo samo eno zanko, ki gre
    istočasno po obeh seznamih. Aha, takole?</p>

<pre>
for ime in imena:
for teza in teze:
    print(ime, ": ", teza)
</pre>

<p>Ummm, ne. Ena zanka je ena zanka. To sta dve. Običajni rešitvi tega problema
    sta dve. To, ki bi bila večini bližje, bom danes zamolčal, iz vzgojnih
    razlogov (kdor jo bo odkril sam, jo pač bo; žal). Funkcija <code>zip</code>
    združi dva seznama (ali več seznamov) v seznam terk.</p>

<pre>>>> zip(teze, imena)
[(74, 'Anze'), (82, 'Benjamin'), (58, 'Cilka'), (66, 'Daniel'), (61, 'Eva'), (84, 'Franc')]
>>> zip(teze, imena, studentka)
[(74, 'Anze', False), (82, 'Benjamin', False), (58, 'Cilka', True), (66, 'Daniel', False), (61, 'Eva', True), (84, 'Franc', False)]
>>> zip(teze, imena, studentka, teze)
[(74, 'Anze', False, 74), (82, 'Benjamin', False, 82), (58, 'Cilka', True, 58), (66, 'Daniel', False, 66), (61, 'Eva', True, 61), (84, 'Franc', False, 84)]</pre>

<p><b>Opomba</b>: tudi tale izpis je iz starega Pythona. Od verzije 3.0 si
    lahko le predstavljamo, da <code>zip</code> dela takole. V resnici naredi
    nekaj majčkeno drugačnega (kaj, je za nas ta mesec še prezapleteno),
    rezultat pa je isti.</p>

<p>Zipamo lahko vse, prek česar lahko naženemo zanko for. Torej ne le seznamov,
    temveč tudi nize, terke in še kaj.</p>

<pre>>>> zip("abcd", "ABCD")
[('a', 'A'), ('b', 'B'), ('c', 'C'), ('d', 'D')]
>>> zip("abcd", range(4))
[('a', 0), ('b', 1), ('c', 2), ('d', 3)]</pre>

<p>Rešimo torej nalogo: izpišimo imena in teže iz ločenih seznamov.</p>

<pre>
for ime, teza in zip(imena, teze):
    print(ime, ": ", teza)
</pre>

<p>Za konec pa izpišimo še poprečno težo študentk.</p>

<pre>skupna_teza = 0
studentk = 0
for teza, je_zenska in zip(teze, studentka):
    if je_zenska:
        skupna_teza += teza
        studentk += 1
print(skupna_teza / (studentk or 1))</pre>



<h2>Dolžina seznama, terke, niza</h2>

<p>Seznami, terke in naši stari znanci nizi imajo nekaj skupnega. Pravzaprav
    veliko skupnega. Razlikujejo se le v podrobnostih. Skupno jim je, recimo,
    da imajo vsi trije dolžino. Gornji seznami šestih tež, šestih imen in
    šestih indikatorjev spola so dolžine 6. Terka <code>1, 2, 3, 4</code> je
    dolžine 4 in niz "Benjamin" je dolžine 8. Dolžine reči, ki imajo dolžino,
    nam pove funkcija <code>len</code>. To sem napisal tako imenitno, da bom
    moral še enkrat, da bo sploh kdo razumel: funkcija <code>len</code>sprejme
    en argument, recimo seznam, terko ali niz in kot rezultat vrne dolžino
    tega seznama, terke ali niza.</p>

<pre>>>> b = 'Benjamin'
>>> len(b)
8
>>> len(podatki)
6
>>> len((1, 2, 3))
3
>>> len(12)
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
TypeError: object of type 'int' has no len()</pre></p>

<p>Morda je koga presenetilo zadnje: številka 12 bi lahko bila dolga 12, ne?
    Ali pa 2, ker ima dve števki? Ne. Funkcija <code>len</code> v bistvu pove
    <em>število elementov, ki jih vsebuje podani argument</em>. Niz "Benjamin"
    vsebuje 8 znakov, seznam <code>podatki</code> vsebuje 6 podseznamov in
    terka <code>(1, 2, 3)</code> ima tri elemente. Število 12 pa nima
    elementov.</p>

<p>Še ena prikladna značilnost seznamov (nizov, terk in še česa): prazni
    seznami so, tako kot prazni nizi, neresnični. Seznam lahko uporabimo v
    pogoju.
<pre>if s:
    print("Seznam s ni prazen")
else:
    print("Seznam s je prazen")</pre>


<h2>Indeksiranje</h2>

<p>Do elementov seznamov, terk in nizov ne pridemo le z zanko for. Dobimo jih
    lahko tudi tako, da preprosto zahtevamo element na tem in tem mestu.
    Vzemimo za primer seznam imen. Spomnimo se, kako je videti.</p>

<pre>>>> imena
['Anze', 'Benjamin', 'Cilka', 'Dani', 'Eva', 'Franc']</pre>

<p>Spremenljivka <code>imena</code> vsebuje šest elementov. Če hočemo dostopati
    do posameznega elementa - recimo izpisati njegovo vrednost - povemo njegov
    indeks, "zaporedno številko". Zapišemo jo v oglate oklepaje za imenom
    spremenljivke, takole:</p>

<pre>>>> imena[2]
'Cilka'</pre>

<p>Se pravi, <code>imena[2]</code> vrne drugi element seznama.</p>

<p>Emmm, drugi?! Mar ni drugi element Benjamin, ne Cilka? Drži, ampak kakor
    šteje python, je drugi element Cilka. Anže je pa ničti. Ne le v pythonu,
    skoraj v vseh jezikih štejemo od 0. Prvi element ima <em>indeks</em> 0,
    drugi element 1 in tretji 2. Zakaj? Razlogi so tehnični in praktični.
    Tehničnega boste razumeli, ko boste (če boste) poslušali predavanja iz Cja.
    Tradicionalno indeks pomeni "odmik od začetka": ko je odmik 0, dobimo prvi
    element in ko je odmik 2, se odmaknemo dva elementa, torej pristanemo na
    tretjem. Medtem ko je v Cju (in še nižjih jezikih) ta, tehnični, argument
    morda smiseln, upravičimo štetje od ničle v Pythonu in drugih višjih
    jezikih s praktičnostjo: reči se tako lepše izidejo. Boste videli.</p>

<p>Če je koga zmedlo, povejmo na glas: oglati oklepaji imajo dve vlogi. Prej
    smo jih uporabljali, da smo vanje zaprli seznam, zdaj vanje zapiramo
    indekse. Naj vas to ne vznemirja, python bo že pravilno razumel, kaj
    mislite, celo v tako hecnih situacijah, kot je tale:</p>

<pre>>>> [3, 1, 4, 1, 5, 9][2]
4</pre>

<p>Prvi oklepaji definirajo seznam, drugi zaprejo indeks, 2, ki pove, kateri
    element tega seznama nas zanima.<br/>
[<br/>
Zveni bedasto in neuporabno? Potem mi povejte, ali je bedasto in neuporabno
    tole:
<pre>["moski", "zenska"][spol[0]]</pre>
in tole
<pre>"MZ"[spol[0]]</pre>
]
</p>

<p>Na enak način kot sezname indeksiramo tudi terke in nize.</p>
<pre>>>> 'Benjamin'[0]
'B'
>>> 'Benjamin'[2]
'n'</pre>

<p>Kadar seznam vsebuje sezname, bomo včasih uporabljali dvojne indekse.
    Spomnimo se seznama <code>podatki</code>: vsebuje šest elementov, in ti
    elementi so spet seznami s po tremi elementi, ki predstavljajo težo, ime
    in spol. Vzemimo, recimo, drugi element:</p>

<pre>>>> en_student = podatki[2]
>>> en_student
[58, "Cilka", True]</pre>

<p>Zdaj lahko o Cilki nekaj povemo.</p>

<pre>>>> print(en_student[1], "tehta", en_student[0], "kilogramov.")
Cilka tehta 58 kilogramov.</pre>

<p>Lahko pa opravimo oboje v enem zamahu.</p>

<pre>>>> print(podatki[2][1], "tehta", podatki[2][0], "kilogramov.")</pre>

<p><code>podatki[2][0]</code> pomeni (če preberemo z desne) ničti element
    drugega elementa seznama <code>podatki</code>. Če se vam zdi to hudo, vas
    lahko potolažim, da ni: v resnici je še bolj grozno. Ker je
    <code>podatki[2][1]</code> niz, se lahko vprašamo po, recimo, tretji črki
    tega niza.

<pre>>>> print("Tretja crka niza", podatki[2][1], "je", podatki[2][1][3])</pre>

<p>(V kost za glodanje C-jašem pa naj vprašam, ali
    <code>podatki[2][1][3][0][0][0][0]</code> kaj izpiše ali se pritoži, da je
    tu nekaj narobe. Ampak to je pa <em>res</em> neuporabno.)</p>

<p>Kaj se zgodi, če je indeks prevelik? Nič lepega.</p>

<pre>>>> "Benjamin"[100]
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
IndexError: string index out of range</pre>

<p>Kako velik pa je lahko indeks? Če ima niz osem črk in je prva ničta, je
    zadnja sedma. Indeks mora biti torej manjši od dolžine - največji dovoljeni
    indeks je tisto, kar vrne funkcija <code>len</code>, minus 1.</p>

<p>Python (in še marsikateri današnji jezik) ima še en trik: indeksiranje s
    konca: -1 je zadnji element, -2 predzadnji in tako naprej.</p>

<pre>>>> 'Benjamin'[-1]
'n'
>>> 'Benjamin'[-2]
'i'
>>> 'Benjamin'[-3]
'm'</pre>


<h2>Rezanje</h2>

<p>Poleg indeksiranja, ki vrača elemente nizov, seznamov, terk (in še česa),
    pozna Python še rezanje (<em>slice</em>), ki vrača dele nizov, seznamov,
    terk (in še česa). Rezino opišemo z indeksom prvega elementa in indeksom
    prvega elementa, ki ga ne želimo več vključiti v rezino. Med indeksa
    postavimo dvopičje. Se pravi, rezina 2:5 pomeni vse elemente od onega z
    indeksom 2 do tistega z indeksom 4 (ne 5!).</p>

<p>Smo to že kje videli? Smo, seveda. Funckija <code>range</code> uporablja
natančno isto logiko. Tako kot pri <code>range</code>, je tudi pri rezanju
to odlična ideja.</p>

<p>Oglejmo si, kaj na to pravi Benjamin.</p>
<pre>>>> b[2:5]
'nja'
>>> b[5:8]
'min'
>>> b[2:5]+b[5:8]
'njamin'</pre>

<p>Spodnjo ali zgornjo mejo smemo tudi izpustiti. V tem primeru dobimo vse
    elemente od začetka oz. do konca. Tu bosta izkazali svojo moč prav obe
    navidez neintuitivni pravili - štetje od 0 in to, da rezina ne vključuje
    zadnjega elementa.</p>

<pre>>>> b[:5]
>>> b[:5]
'Benja'
>>> b[5:]
'min'</pre>

<p><code>b[:5]</code> vrne prvih pet elementov. <code>b[5:]</code> vrne vse
    od petega naprej; ker štejemo od 0, to pomeni, da izpustimo prvih pet. Se
    pravi, če želimo nizu <code>s</code> odbiti prvih pet znakov, bomo rekli</p>

<pre>s = s[5:]</pre>

<p>Da peti študent vstane le enkrat, nam pride prav, če želimo v niz kaj
    vriniti. Če bi radi za petim znakom niza vrinili X, to storimo takole:</p>

<pre>>>> b[:5]+"X"+b[5:]
'BenjaXmin'</pre>

<p>Ste opazili, da nam sploh ni bilo treba pomisliti na to, da štejemo od 0?
    Vidite, kako naravno je to. Če bi šteli od 1, bi bilo tole precej bolj
    zapleteno.</p>

<p>Še dodatne možnosti prinese indeksiranje od zadaj. Iz niza lahko poberemo,
    recimo, elemente od predpredpredzadnjega (-5) do predzadnjega (-2). Koliko
    jih bo? Trije, seveda.</p>

<pre>>>> b[-5:-2]
'jam'</pre>

<p>No, tegale najbrž ne uporabimo velikokrat. Pač pa nas pogosto zanimajo,
    recimo, zadnji štirje znaki. Ali pa vsi razen zadnjih štirih.</p>

<pre>>>> film = "Babylon 5 - 3x04 - Passing through Gethsemane.avi"
>>> film[-4:]
'.avi'
>>> film[:-4]
'Babylon 5 - 3x04 - Passing through Gethsemane'</pre>

<p>Mimogrede, tole sicer varneje delamo s funkcijo, ki smo jo že omenili,
    namreč <code>splitext</code>, ki prejme kot argument ime datoteke in vrne
    terko z dvema elementoma, imenom datoteke brez končnice in končnico.</p>

<p>Kako pa bi od niza odbili prve tri in zadnja dva znaka? Takole:</p>

<pre>>>> b[3:-2]
'jam'</pre>

<p>Že tale primer pokaže, zakaj je štetje od 0 in čudno pravilo, po katerem je
    prvi element rezine vključen, zadnji pa ne, tako smiselno in uporabno.
    Tisti, ki bi v vsej stvari vendarle videli še kako logiko, pa bo morda
    prepričala spodnja tabelica, ob kateri lahko še enkrat premislijo vse
    primere.</p>

<table>
    <tr>
        <td>0</td><td/><td>1</td><td/><td>2</td><td/><td>3</td><td/><td>4</td><td/><td>5</td><td/><td>6</td><td/><td>7</td><td/><td>8</td><td/>
    </tr>
    <tr>
        <td></td><td>B</td><td/><td>e</td><td/><td>n</td><td/><td>j</td><td/><td>a</td><td/><td>m</td><td/><td>i</td><td/><td>n</td></td>
    </tr>
    <tr>
        <td>-8</td><td/><td>-7</td><td/><td>-6</td><td/><td>-5</td><td/><td>-4</td><td/><td>-3</td><td/><td>-2</td><td/><td>-1</td><td/>
    </tr>
</table>

<p>Vsi znaki med drugim in petim so 'nja', znaki od 3 do -2 so 'jam'... In tako
    naprej.</p>

<p>Vendar še nismo končali. Izpustimo lahko tudi zgornjo in spodnjo mejo. Kaj
    dobimo v tem primeru? Cel niz. Je to uporabno? Na nizih pravzaprav ne. Pri
    čem drugem pa nam bo prišlo še prav.</p>

<p>Poleg meja rezine lahko podamo tudi <em>korak</em>. Namesto vsakega znaka
    lahko zahtevamo, recimo, vsak drugi znak, tako da dodamo še eno dvopičje,
    ki mu sledi velikost koraka.</p>

<pre>>>> '0123456789'[2:9]
'2345678'
>>> '0123456789'[2:9:2]
'2468'
>>> '0123456789'[2:9:3]
'258'
>>> '0123456789'[2:9:4]
'26'</pre>

<p>Korak je lahko, tako kot pri <code>range</code> tudi negativen! V tem
    primeru je potrebno zamenjati meji - prva mora biti višja od druge.</p>

<pre>>>> '0123456789'[9:2:-1]
'9876543'
>>> '0123456789'[9:2:-2]
'9753'</pre>

<p>Meje smemo seveda spet tudi izpuščati:</p>

<pre>>>> '0123456789'[9::-1]
'9876543210'</pre>

<p>Takole obrnemo predavatelja.</p>

<pre>>>> 'demšar janez'[::-1]
'zenaj rašmed'</pre>

<p>Vse tole je videti nekoliko zapleteno in tuje. In morda je: povaditi bo
    treba, pa se bo udomačilo. Pa se splača? Za odbijanje znakov od nizov? Se!
    Lepota je v tem, da se natanko enako kot indeksiranje in rezanje nizov
    obnaša tudi indeksiranje seznamov in vsega drugega. Pa še kaj - zanke
    <code>for</code>, recimo, ki jih bomo vsak čas spoznali.</p>

<p>Poglejmo si torej še rezanje seznamov.</p>

<pre>>>> imena = ["Anze", "Benjamin", "Cilka", "Dani", "Eva", "Franc"]
>>> imena[2:5]
['Cilka', 'Dani', 'Eva']
>>> imena[2:]
['Cilka', 'Dani', 'Eva', 'Franc']
>>> imena[:2]
['Anze', 'Benjamin']
>>> imena[:-2]
['Anze', 'Benjamin', 'Cilka', 'Dani']
>>> imena[-2:]
['Eva', 'Franc']
>>> imena[::-1]
['Franc', 'Eva', 'Dani', 'Cilka', 'Benjamin', 'Anze']</pre>

<p><a href="http://www.youtube.com/watch?v=G2eUopy9sd8">Že videno.</a> Rezanje
    seznamov se vede enako kot rezanje nizov. Rezanje terk pa prav tako.</p>


<h2>Spreminjanje seznamov z indeksiranjem in rezanjem</h2>

<p>Tole je preprosto. Vsak element seznama se vede na nek način kot
    spremenljivka: lahko mu priredimo vrednost in s tem "povozimo" prejšnjo
    vrednost.</p>

<pre>>>> imena
['Anze', 'Benjamin', 'Cilka', 'Dani', 'Eva', 'Franc']
>>> imena[3] = "Daniel"
>>> imena
['Anze', 'Benjamin', 'Cilka', 'Daniel', 'Eva', 'Franc']</pre>

<p>Tako kot prej lahko tudi zdaj indeksiramo od spredaj ali od zadaj.</p>

<p>(Za tiste, ki znate kak drug jezik, predvsem Php: elementov ni mogoče
    dodajati s prirejanjem! Pythonovi seznami niso ekvivalentni Phpjevim: temu,
    česar se v phpju reče <code>array</code>, je bližji pythonov slovar
    (<em>dictionary</em>, <code>dict</code>), ki ga bomo spoznali v
    prihodnosti.)</p>

<p>Pa rezine? Glede na to, da je rezina podseznam, moramo tudi pri prirejanju
    rezin prirejati podsezname.</p>

<pre>>>> imena
['Anze', 'Benjamin', 'Cilka', 'Daniel', 'Eva', 'Franc']
>>> imena[1:4]=["Ben", "Cecilija", "Dani"]
>>> imena
['Anze', 'Ben', 'Cecilija', 'Dani', 'Eva', 'Franc']</pre>

<p>Mora biti seznam, ki ga prirejamo, enako dolg kot rezina, ki jo bomo
    povozili? Ne, čemu? Takole zamenjamo tri z dvema:</p>

<pre>>>> imena[1:4]=["Ben-Cecil", "Daniel"]
>>> imena
['Anze', 'Ben-Cecil', 'Daniel', 'Eva', 'Franc']
</pre>

<p>Ali pa nobenega s tremi:</p>

<pre>>>> imena[2:2] = ["D2", "D3", "D4"]
>>> imena
['Anze', 'Ben-Cecil', 'D2', 'D3', 'D4', 'Daniel', 'Eva', 'Franc']</pre>

<p>Z rezinami lahko tudi pobrišemo del seznama.</p>

<pre>>>> imena
['Anze', 'Ben-Cecil', 'D2', 'D3', 'D4', 'Daniel', 'Eva', 'Franc']
>>> imena[2:5]
['D2', 'D3', 'D4']
>>> imena[2:5]=[]
>>> imena
['Anze', 'Ben-Cecil', 'Daniel', 'Eva', 'Franc']</pre>

<p>Za brisanje obstaja še veliko drugih načinov, recimo tale</p>
<pre>>>> imena
['Anze', 'Ben-Cecil', 'Daniel', 'Eva', 'Franc']
>>> del imena[2]
>>> imena
['Anze', 'Ben-Cecil', 'Eva', 'Franc']
>>> del imena[1:3]
>>> imena
['Anze', 'Franc']</pre>

<p>Če kdo pričakuje, da bomo zdaj povedali še, da enako delamo tudi z nizi in
    terkami ... se moti. Nizov in terk ne moremo spreminjati!</p>

<pre>>>> b = 'Benjamin'
>>> b[2]='a'
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
TypeError: 'str' object does not support item assignment</pre>

<p>Tu je torej osnovna razlika med seznamom in terko: seznam je spremenljiv,
    terka ne. Tudi niza ne moremo spreminjati, kakor smo pravkar videli. Kako
    pa bi potem zamenjali tretji znak niza b s črko 'a'?</p>

<pre>>>> b = b[:2]+'a'+b[3:]
>>> b
'Beajamin'</pre>

<p>To je seveda nerodno. Čemu je torej tako? Čemu ne moremo spreminjati nizov
    tako, kot sezname? (In čemu sploh ta trapasta terka?) Videli bomo, da nam
    pride včasih zelo zelo prav, da so nekateri objekti nespremenljivi.
    (Nekateri - pogosto tudi jaz - pravijo celo, da jeziki sploh ne bi smeli
    dopuščati spreminjanja spremenljivk.) Nize pa si v resnici redko želimo
    spreminjati - da, pogosto jih bomo sestavljali ali obtesovali, zelo redko
    pa si želimo spreminjati posamezne črke. Zato nas to, da so konstantni, ne
    bo preveč motilo, velikokrat pa nam bo koristilo.</p>


<h2>Računske operacije na seznamih (in drugod)</h2>

<p>V svojem prvem soočenju s programiranjem smo spoznali aritmetične izraze:
    seštevali in množili smo števila, jih kvadrirali in računali sinuse.
    Zadnjič smo naleteli na logične izraze, kjer smo računali z logičnimi
    vrednostmi, <code>True</code> in <code>False</code>. Danes je čas, da se
    nehamo čuditi ob vsakem izrazu posebej in jim dajati pridevke "aritmetični"
    "logični" in tako naprej. Računati se da pač z različnimi rečmi in ena od
    teh reči so tudi seznami.</p>

<p>Lahko sezname seštevamo? Kaj dobimo, če seštejemo <code>[2, 5, -1]</code> in
    <code>[3, 7, 4]</code>? Dobimo <code>[5, 12, 3]</code> ali
    <code>[2, 5, -1, 3, 7, 4]</code>? Oboje bi bilo smiselno, odgovor pa je
    takšen: če so se seznami doslej vedli tako podobno nizom, naj se še glede
    seštevanja.Ker je <code>'abc' + 'def'</code> enako <code>'abcdef'</code>,
    naj bo tudi <code>[2, 5, -1] + [3, 7, 4]</code> enako
    <code>[2, 5, -1, 3, 7, 4]</code>.</p>

<p>Podobno je z množenjem. <code>[2, 5, -1] * 2</code> bi moralo biti po vsej
    logiki enako <code>[2, 5, -1] + [2, 5, -1]</code>, se pravi
    <code>[2, 5, -1, 2, 5, -1]</code>. In tudi je.</p>

<p>K seznamu lahko prištejemo le seznam, k nizu niz, k terki terko. Vse tri pa
    lahko pomnožimo s celim številom - in z ničemer drugim.</p>

<p>Poleg <code>+</code> in <code>*</code> pa poznajo vsi trije še dva
    operatorja, <code>in</code> in <code>not in</code>. S prvim vprašamo, ali
    seznam oz. terka vsebujeta določen element in ali niz vsebuje določen
    podniz.</p>

<pre>>>> 1 in [1, 2, 3]
True
>>> 4 in [1, 2, 3]
False
>>> 'in' in 'Benjamin'
True
>>> 'an' in 'Benjamin'</pre>

<p>Drugi je seveda ravno nasproten, z njim se vprašamo ali seznam (niz)
    <em>ne vsebuje</em> elementa (podniza).</p>

<pre>>>> 1 not in [1, 2, 3]
False
>>> 4 not in [1, 2, 3]
True
>>> 'in' not in 'Benjamin'
False
>>> 'an' not in 'Benjamin'
True</pre>

<p>V resnici <code>not in</code> ni prav potreben, saj je
    <code>x not in l</code> isto kot <code>not x in l</code>.</p>



</body>
</html>