Testi

Testi: testi-neobcutljivi-slovar.py

Naloga

Sestavi razred WordDict, ki se bo vedel podobno kot slovar, vendar bo predpostavljal, da so ključi nizi in bo pri indeksiranju zanemaril razliko med malimi in velikimi črkami. Če je torej velikosti nek takšen slovar in napišemo velikosti["Ana"] = 165, lahko do tega elementa pridemo z velikosti["Ana"], velikosti["ana"], velikosti["ANA"], ali, recimo, velikosti["AnA"]. Razliko med velikostmi črk zanemarjamo tudi pri prirejanju: če gornjemu slovarju priredimo velikosti["aNA"] = 170, nova vrednost povozi staro, čeprav smo imeli prej "Ana" in zdaj "aNA".

Poleg tega naj WordDict podpira tudi metode keys, values in items, ki morajo delati isto kot pri običajnem slovarju; ključi, ki jih vračajo, morajo biti takšni, ko smo jih podali (v gornjem primeru torej "Ana").

Slovar naj podpira tudi operator len: možno naj bo torej poklicati len(velikosti).

Način, na katerega rešite nalogo, je v celoti prepuščen vam: novi slovar smete izpeljati iz starega, lahko ga definirate na novo, ali kaj tretjega.

Dodano: Slovarjev konstruktor (__init__) naj kot argument sprejme seznam parov (kljuc, vrednost) in jih shrani.

Namig, če slučajno ne veste: če želimo pri dveh nizih zanemariti velikost črk, primerjamo tadva niza, pretvorjena v same male črke.

Rešitev

Brez dedovanja: Naredi si sam

Naš objekt, self, bo vseboval seznam z imenom self.dictionary. Če bodo v slovarju elementi "Ana": 65, "beRTA": 93 in "CILKA": 58, bo vsebina seznama enaka self.dictionary = [("Ana", 65), ("beRTA", 93), ("CILKA", 58)]. Vse funkcije, ki jih moramo napisati, so le telovadba s slovarji:

  • __getitem__(self, key) poišče tisti par v seznamu self.dictionary, pri katerem je prvi element enak ključu key in vrne drugi element - pri tem (in tudi v vseh prihodnjih točkah) sta dva ključa enaka, če sta enaka po tem, ko ju pretvorimo v male črke;
  • __setitem__(self, key, value) doda v self.dictionary par (key, value), predtem pa poišče in pobriše morebitni element, ki se že ujema s ključem;
  • __len__(self), vrne dolžino seznama self.dictionary;
  • keys(self) vrne prve elemente parov iz seznama self.dictionary;
  • values(self) vrne druge elemente parov iz seznama self.dictionary;
  • items(self) vrne pare iz seznama self.dictionary.
  • __init__(self, s) pokliče __setitem__ za vsak element seznama s
Torej tako: class WordDict: def __init__(self, s): self.dictionary = [] for key, value in s: self[key] = value def __getitem__(self, key): for dkey, devalue in self.dictionary: if dkey.lower() == key.lower(): return devalue def __setitem__(self, key, value): for i, (dkey, devalue) in enumerate(self.dictionary): if dkey.lower() == key.lower(): self.dictionary[i] = (key, value) break else: self.dictionary.append((key, value)) def __len__(self): return len(self.dictionary) def keys(self): ks = [] for dkey, devalue in self.dictionary: ks.append(dkey) return ks def values(self): vs = [] for dkey, devalue in self.dictionary: vs.append(devalue) return vs def items(self): return self.dictionary[:]

Z dedovanjem

Veliko lažje je nekoliko dopolniti dict. Dodali mu bomo še en slovar, imenujmo ga lowkeys. Ko bo imel pravi slovar vsebino {"Ana": 65, "beRTA": 93 in "CILKA": 58}, bo v self.lowkeys enak {"ana": "Ana", "berta": "beRTA", "cilka": "CILKA"} - ključi tega slovarja so torej besede, zapisane z malimi črkami, vrednosti pa te besede, kakršne se pojavljajo v "pravem" slovarju.

Zdaj moramo postoriti le tole:

  • __init__(self, s) pokliče __setitem__ za vsak element; s
  • __getitem__(self, key) spremeni ključ key v male črke, s pomočjo slovarja self.lowkeys, kako se ta ključ imenuje v "pravem" slovarju in vrne ta element tako, da pokliče podedovani __getitem__;
  • __setitem__(self, key, value) na podoben način preveri, ali obstaja v velikem slovarju enak ključ in ga pobriše; nato doda v "pravi" slovar "pravi" par, v lowkeys pa shrani ključ z malimi in velikimi črkami.
In to je vse: keys, values, items in __len__ smo podedovali.

class WordDict(dict): def __init__(self, s): self.lowkeys = {} for key, value in s: self[key] = value def __getitem__(self, key): key = self.lowkeys.get(key.lower(), key) return super(WordDict, self).__getitem__(key) def __setitem__(self, key, value): lowkey = key.lower() if lowkey in self.lowkeys: del self[self.lowkeys[lowkey]] super(WordDict, self).__setitem__(key, value) self.lowkeys[lowkey] = key
Zadnja sprememba: četrtek, 25. marec 2021, 21.35