[Tutor] Storing dictionary value, indexed by key, into a variable

Peter Otten __peter__ at web.de
Sat Apr 5 23:14:22 CEST 2014

John Aten wrote:

> I read the article on data driven programming that Danny linked too, and
> did some additional looking around. I couldn't find anything directly
> using Python, but I got an idea of the concept and went crazy with it.
> This may still be off the mark, but I created a complex combination of
> lists and dictionaries to represent each individual instance of each
> demonstrative (starting only with one):
> that_those = [ [ [ {'nom': 'ille', 'clue': 'That/Those, Singular,
> Masculine Nominative'}, {'gen': 'illīus', 'clue': 'That/Those, Singular,
> Masculine Genitive'}, {'dat': 'illī', 'clue': 'That/Those, Singular,
> Masculine Dative'}, {'acc': 'illum', 'clue': 'That/Those, Singular,
> Masculine Accusative'}, {'abl': 'illō', 'clue': 'That/Those, Singular,
> Masculine Ablative'} ], [{'nom': 'illī', 'clue': 'That/Those, Plural,
> Masculine Nominative'},
>                 {'gen': 'illōrum', 'clue': 'That/Those, Plural, Masculine
>                 {Genitive'},
> {'dat': 'illīs', 'clue': 'That/Those, Plural, Masculine Dative'},
> {'acc': 'illōs', 'clue': 'That/Those, Plural, Masculine Accusative'},
> {'abl': 'illīs', 'clue': 'That/Those, Plural, Masculine Ablative'} ] ], [
> [ {'nom': 'illa', 'clue': 'That/Those, Singular, Feminine Nominative'},
>                 {'gen': 'illīus', 'clue': 'That/Those, Singular, Feminine
>                 {Genitive'},
> {'dat': 'illī', 'clue': 'That/Those, Singular, Feminine Dative'},
> {'acc': 'illam', 'clue': 'That/Those, Singular, Feminine Accusative'},
> {'abl': 'illā', 'clue': 'That/Those, Singular, Feminine Ablative'} ], [
> {'nom': 'illae', 'clue': 'That/Those, Plural, Feminine Nominative'},
> {'gen': 'illārum', 'clue': 'That/Those, Plural, Feminine Genitive'},
> {'dat': 'illīs', 'clue': 'That/Those, Plural, Feminine Dative'}, {'acc':
> 'illās', 'clue': 'That/Those, Plural, Feminine Accusative'}, {'abl':
> 'illīs', 'clue': 'That/Those, Plural, Feminine Ablative'} ] ] , [ [
> {'nom': 'illud', 'clue': 'That/Those, Singular, Neuter Nominative'},
>                 {'gen': 'illīus', 'clue': 'That/Those, Singular, Neuter
>                 {Genitive'},
> {'dat': 'illī', 'clue': 'That/Those, Singular, Neuter Dative'},
> {'acc': 'illud', 'clue': 'That/Those, Singular, Neuter Accusative'},
> {'abl': 'illō', 'clue': 'That/Those, Singular, Neuter Ablative'} ], [
> {'nom': 'illa', 'clue': 'That/Those, Plural, Neuter Nominative'},
>                 {'gen': 'illōrum', 'clue': 'That/Those, Plural, Neuter
>                 {Genitive'},
> {'dat': 'illīs', 'clue': 'That/Those, Plural, Neuter Dative'},
> {'acc': 'illa', 'clue': 'That/Those, Plural, Neuter Accusative'},
> {'abl': 'illīs', 'clue': 'That/Those, Plural, Neuter Ablative'} ] ] ]
> Now, this is a big mess, for sure, but it seems possible that it is
> abstract enough that I could reuse the same logic and just switch out the
> data to make different types of similar programs. Also, I can write a
> script to populate this structure to construct a program to drill any type
> of word that is declined by gender, number and case. I can call each item
> pretty easily like this:
> question_to_be_dispalyed_to_user =
> that_those[gender][number][q_and_a]["clue"] answer_to_that_question =
> that_those[gender][number][q_and_a][case]
> Where gender, number, q_and_a, and case follow Peter's suggestion:
> cases = ['nom', 'gen', 'dat', 'acc', 'abl']
> case = random.choice(cases)
> The complete code will follow, but I have a spooky new problem. When I try
> to run the following code, I intermittently get the following error:
> Traceback (most recent call last):
>   File "./latDemTest.py", line 59, in <module>
>     answer = that_those[gender][number][q_and_a][case]
> KeyError: 'abl'
> I looked this error up online, and it seems the key error is generated
> when one attempts to retrieve a value from a dictionary with a key that
> does not exist. The problem is, it seems to me that the keys should in
> fact exist. The odd thing is, the code returns this error sometimes, and
> sometimes it doesn't. I did a bunch of trials, keeping track of which
> particular entries in the data structures worked and which failed, and I
> discovered that they overlap. The dictionary  {'gen': 'illōrum', 'clue':
> 'That/Those, Plural, Neuter Genitive'} for example, happily spits out the
> proper question and answer sometimes, other times it shoots out the
> previously mentioned error. I cannot understand how this could happen!

There are dicts that have a "nom" key, other dicts that have a "gen" key, 
and so on. I didn't read your code completely, but my guess is that you do 
not get a KeyError in the rare case (roughly 1 out 5) that you pick a 
dictionary that handles the same casus as the one you picked independently. 

How would you go on fixing this? I think this little table is a good start:

> # place one: 0 = masculine, 1 = feminine, 2 = neuter
> # place two: 0 = singular, 1 = plural
> # place two:
> # place three: 0 = answer, 1 = clue
> # place four, 'nom' = answer, 'clue' = description
> # So, word[0][0][0]["nom"] should produce: ille

Unfortunately it gets a little fuzzy in the middle. So here's my fixed 

place one, genus: 0=m, 1=f, 2=n
place two, numerus: 0=sg, 1=pl
place three, casus: 0=nom, 1=gen, 2=dat, ...
place four: "answer"=answer, "clue"=description

Everything but place four is a list. That allows for a small simplification: 
As random.choice() works on arbitrary lists you can apply it directly on 
your data:

genus = random.choice(that_those)
numerus = random.choice(genus)
casus = random.choice(numerus)
clue = casus["clue"]
answer = casus["answer"]

Once you have more pronomina you just wrap the whole thing into
place zero, the word: 
   0=(everything from above for that/those), 
   1=(the same structure for this), 
   ... # and so on

However, before you add more data you might give some thought to a format of 
the data that is easier to write and proof-read. You can then write another 
little script that morphs the structure into the one needed by your current 

More information about the Tutor mailing list