Filtri
Testi
Testi: testi-filtri.py
Naloga
V tej nalogi bomo programirali filtre, ki kot argument dobijo seznam in
kot rezultat vrnejo spremenjen seznam. Primer takšnega filtra je filter
Pristej. Ko ga skonstruiramo, povemo, koliko naj prišteva.
Ko ga pokličemo in mu podamo seznam kot argument, vrne nov seznam, v
katerem je vsakemu elementu prišteto, kolikor smo hoteli.
Podoben filter je Pomnozi, ki namesto prištevanja množi.
Filter Obrni obrne podani seznam.
Filter Normaliziraj deli vse elemente seznama z največjim
elementom. (Dodatno, naknadno pojasnilo: če je največji element seznama enak 0,
seznama ne spreminjamo. Predpostaviti smemo tudi, da v seznamu ni negativnih elementov.)
V vseh gornjih primerih smo filter poklicali - kot da bi bil funkcija. Tule je še en primer.
Filtri pa imajo še eno metodo: obdelaj. Ta ne vrača novega
seznama, temveč spreminja obstoječega.
Poleg tega imajo filtri tudi metodo opis, ki vrne
(ne izpiše!) opis filtra.
Končno, filtri imajo tudi metodo izpisi. Ta naredi nekaj
podobnega, kot če pokličemo seznam, le da vrne terko, ki vsebuje novi seznam
in opis spremembe.
Vse skupaj je narejeno takole. Vsi filtri so izpeljani iz razreda
Filter:
Ta razred je takšen, kot je in ga ne smete spreminjati! Razred definira
metodo __call__; ta poskrbi, da je filtre možno poklicati
("kot da bi bili funkcije": objekte razredov, ki imajo metodo
__call__, lahko pokličemo). Poleg tega definira metodo
obdelaj, ki prav tako naredi, kar mora - spreminja seznam.
Obe pa kličeta metodo akcija. Te metoda pa ... ni!
Podobno metoda izpisi kliče metodo akcija,
poleg nje pa še opis, ki ga prav tako ni.
Ogrevalna naloga
Obleci tople nogavice in popij skodelico čaja, po možnosti božičnega ali pa žajbljevega z medom.
Pitja kuhanega vina pred programiranjem ne priporočam, saj po mojih izkušnjah že najmanjša količina zaužitega alkohola (vključno s čajem z rumom) bistveno poveča število trivialnih napak. (Ne nujno: http://imgs.xkcd.com/comics/ballmer_peak.png; hvala, Tejo Ličen!)
Obvezna naloga
Sprogramiraj razrede Pristej, Pomnozi,
Obrni in Normaliziraj. Vsi naj bodo izpeljani iz
Filter. Vsak razred naj definira metodi akcija
in opis. Kjer je potrebno, definiraj še konstruktor
__init__. Dodajanje drugih metod je prepovedano! Spreminjanje
metod obdelaj, __call__ ali izpisi
je še bolj prepovedano. Spreminjanje razreda Filter je najbolj
prepovedano.
Nize, ki jih mora vračati opis, si lahko ogledate zgoraj.
Metoda akcija naj sprejme seznam in vrne nov, "filtrirani"
seznam. V bistvu akcija naredi tisto, kar se zgodi, ko pokličemo
filter.
Dodatna naloga
Sprogramiraj funkcije (ne metode!) izvedi,
obdelaj in preveri.
Recimo, da imamo seznam filtrov in seznam, ki bi ga radi spustili prek teh filtrov.
Funkcija izvedi dobi kot argument seznam filtrov in seznam.
Vrne prefiltriran seznam - seznam, ki gre prek vseh naštetih filtrov.
Funkcija preveri je podobna, le da namesto seznama vrne
terko: novi seznam in opis poteka.
Funkcija obdelaj je podobna funkciji izvedi,
le da ne vrača novega seznama temveč spreminja obstoječega.
Rešitev
Obvezna naloga
Da rešimo nalogo, moramo narediti le, kar pravi naloga: vsakemu razredu
dodamo metodi akcija in opis. Metode same po sebi
so tako preproste, da me skrbi, če zaradi njihove trivialnosti niste bili
nekoliko užaljeni.
Poleg tega pa nekateri razredi potrebujejo konstruktor. Kateri? Tisti, ki
si morajo kaj zapomniti, shraniti pri sebi kaj takšnega, kar potrebujejo za
delovanje. Filtra Obrni in Normaliziraj nista takšna:
vsako zaporedje, ki ga dobita, pač obrneta oziroma normalizirata. Filtra
Pristej in Pomnozi pa morata vedeti, s čim naj
pomnožita podano zaporedje. To ni parameter, ki bi ga podali ob klicu filtra
(ali klicu metode akcija), temveč ga podamo konstruktorju in
filter si ga zapomni za vedno. Tadva torej potrebujeta konstruktor, ki bo nekam
v objekt (self) zapisal vrednost podanega argumenta.
Dodatna naloga
Dodatna naloga zahteva le, da po vrsti pokličemo vse filtre iz seznama.