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.