I started programming in Python as a hobby a few weeks ago, and I have run into a little problem. I am currently making a script to give me a sort of Vocabulary Test. It is kind of hard to explain so I will just show you the code.

words = ["aero", "aesthet", "andr", "arch", "arch", "ast", "baro",\
"biblio", "bio", "cardi", "chron", "cosm", "crat", "cycl", "dem", "dont",\
"dogma", "dox", "esth"]

answers = ["air", "sense", "man", "man", "chief", "ancient", "star", "weight",\
"book", "life", "heart", "time", "universe", "rule", "circle", "people",\
"tooth", "opinion", "belief", "feeling"]

a = 0

def test():
    a = a + 1
    print "What does", words[a], "mean?"
    ans = raw_input("> ")
    if ans == answers[a]:
        print "Correct!"
        test()
    else:
        print "That is incorrect. Try again."
        a = a - 1
        test()

test()

So, the error I get is:

Traceback (most recent call last):
File "C:\Users\Pat\Python Scripts\Scripts in Progress\Testing - Copy (10).py", line 26, in <module>
test()
File "C:\Users\Pat\Python Scripts\Scripts in Progress\Testing - Copy (10).py", line 15, in test
a = a + 1
UnboundLocalError: local variable 'a' referenced before assignment

I made my script thinking I would just be able to loop through all of the words, except since I am having a problem with my "a" variable I am stuck... And I am pretty sure I have another bug in my script with returning "a"...

Would anybody be able to help?

Thanks in advance.

Recommended Answers

All 12 Replies

Well, I asked one of my Python friends and he gave me the answer. Feel free to delete/do whatever with post.

For the many of you who still want to know the solution, make variable 'a' a global:

words = ["aero", "aesthet", "andr", "arch", "arch", "ast", "baro",\
"biblio", "bio", "cardi", "chron", "cosm", "crat", "cycl", "dem", "dont",\
"dogma", "dox", "esth"]

answers = ["air", "sense", "man", "man", "chief", "ancient", "star", "weight",\
"book", "life", "heart", "time", "universe", "rule", "circle", "people",\
"tooth", "opinion", "belief", "feeling"]

a = 0

def test():
    global a
    a = a + 1
    print "What does", words[a], "mean?"
    ans = raw_input("> ")
    if ans == answers[a]:
        print "Correct!"
        test()
    else:
        print "That is incorrect. Try again."
        a = a - 1
        test()

test()

For the many of you who still want to know the solution, make variable 'a' a global:

That or simply pass a to test:

words = ["aero", "aesthet", "andr", "arch", "arch", "ast", "baro",\
"biblio", "bio", "cardi", "chron", "cosm", "crat", "cycl", "dem", "dont",\
"dogma", "dox", "esth"]

answers = ["air", "sense", "man", "man", "chief", "ancient", "star", "weight",\
"book", "life", "heart", "time", "universe", "rule", "circle", "people",\
"tooth", "opinion", "belief", "feeling"]

a = 0

def test(a):
    a = a + 1
    print "What does", words[a], "mean?"
    ans = raw_input("> ")
    if ans == answers[a]:
        print "Correct!"
        test()
    else:
        print "That is incorrect. Try again."
        a = a - 1
        test()

test(a)

Wow you guys ARE extremely helpful. I'm really starting to like this site. Well thanks for all the extra info, I learned a few more things.

Except that neither one thought to test for a < 0 (if someone doesn't know any of the words) or a => len(words). Also, you have 19 words and 20 answers. When doing this type of programming it is better to
(a) use a dictionary with the word as the key, pointing to the answer
(b) or at least test that len(words) == len(answers) especially if you are going to modify the lists at any time.

That or simply pass a to test:

words = ["aero", "aesthet", "andr", "arch", "arch", "ast", "baro",\
"biblio", "bio", "cardi", "chron", "cosm", "crat", "cycl", "dem", "dont",\
"dogma", "dox", "esth"]

answers = ["air", "sense", "man", "man", "chief", "ancient", "star", "weight",\
"book", "life", "heart", "time", "universe", "rule", "circle", "people",\
"tooth", "opinion", "belief", "feeling"]

a = 0

def test(a):
    a = a + 1
    print "What does", words[a], "mean?"
    ans = raw_input("> ")
    if ans == answers[a]:
        print "Correct!"
        test()
    else:
        print "That is incorrect. Try again."
        a = a - 1
        test()

test(a)

This will give you an error:
Traceback (most recent call last):
File "<module1>", line 23, in <module>
File "<module1>", line 21, in test
TypeError: test() takes exactly 1 argument (0 given)

Well, rather than doing a global, and taking that passing the variable raises an error, I did everything inside the function and I checked if the number of words was equal to the number of answers. I also changed the way it would redo the problem, to make sure it wouldn't go into the negatives.

words = ["aero", "aesthet", "andr", "anthr", "arch", "arch", "ast", "baro",\
"biblio", "bio", "cardi", "chron", "cosm", "crat", "cycl", "dem", "dont",\
"dogma", "dox", "esth"]

answers = ["air", "sense", "man", "man", "chief", "ancient", "star", "weight",\
"book", "life", "heart", "time", "universe", "rule", "circle", "people",\
"tooth", "opinion", "belief", "feeling"]

def test():
    if len(words) == len(answers):
        a = 0
        loop = 1
        while loop == 1:
            if a == len(words):
                print "You are done."
                loop = 0
            else:
                b = a + 1
                print b, ".", "What does", words[a], "mean?"
                ans = raw_input("> ")
                if ans == answers[a]:
                    print "Correct!"
                    a = a + 1
                else:
                    print "That is incorrect. Try again."          

test()

Also, is there a benefit to doing this with a dictionary?

Here would be your program using a dictionary ...

def test(d):
    for word in d.keys():
        count = 0
        while True:
            print "What does", word, "mean?"
            ans = raw_input("> ")
            if ans == d[word]:
                print "Correct!"
                break
            else:
                print "That is incorrect. Try again."
                count += 1
                # ask 3 times then go on to the next word
                if count >= 3:
                    break

words = ["aero", "aesthet", "andr", "arch", "arch", "ast", "baro",
"biblio", "bio", "cardi", "chron", "cosm", "crat", "cycl", "dem",
"dont", "dogma", "dox", "esth"]

answers = ["air", "sense", "man", "man", "chief", "ancient", "star",
"weight", "book", "life", "heart", "time", "universe", "rule",
"circle", "people","tooth", "opinion", "belief", "feeling"]

# create a dictionary of word:answer pairs
d = dict(zip(words, answers))
 
print d  # testing only

test(d)

Actually the code example below shows you the advantage of using a dictionary a little better. You can modify the dictionary easier or add to it. It keeps the word and answer pair together. On top of that you can easily save and load the modified dictionary via a file ...

# word and answer quiz using a dictionary
# optional file save and load

import pickle

def test(d):
    for word in d.keys():
        count = 0
        while True:
            print "What does", word, "mean?"
            ans = raw_input("> ")
            if ans == d[word]:
                print "Correct!"
                break
            else:
                print "That is incorrect. Try again."
                count += 1
                # ask 3 times then go on to the next word
                if count >= 3:
                    break

def save_d(filename, d):
    '''save the dictionary to a file'''
    fout = open(filename, "w")
    pickle.dump(d, fout)
    fout.close()

def load_d(filename):
    '''load the dictionary from a file'''
    fin = open(filename, "r")
    d = pickle.load(fin)
    fin.close()
    return d


# use a dictionary of word:answer pairs
# this keeps word and answer together and is easier to add to
d = {
'crat': 'universe',
'bio': 'book',
'cardi': 'life',
'dont': 'people',
'ast': 'ancient',
'cosm': 'time',
'aero': 'air',
'esth': 'belief',
'dogma': 'tooth',
'cycl': 'rule',
'dox': 'opinion',
'aesthet': 'sense',
'biblio': 'weight',
'dem': 'circle',
'chron': 'heart',
'arch': 'chief',
'baro': 'star',
'andr': 'man'
}

# optionally save and load any dictionary changes
filename = "word_answer.dat"
save_d(filename, d)
d = load_d(filename)

test(d)

Another way to build the lists

words = """
    aero aesthet andr arch arch ast baro
    biblio bio cardi chron cosm crat cycl dem
    dont dogma dox esth
""".strip().split()

I'd use a while loop if you're gonna use two different lists. If you want to use a for loop, I'd suggest using a dictionary to store values and keys.

Here's an example of the while loop:

words = ["aero", "aesthet", "andr", "arch", "arch", "ast", "baro",\
"biblio", "bio", "cardi", "chron", "cosm", "crat", "cycl", "dem", "dont",\
"dogma", "dox", "esth"]

answers = ["air", "sense", "man", "chief", "ancient", "star", "weight",\
"book", "life", "heart", "time", "universe", "rule", "circle", "people",\
"tooth", "opinion", "belief", "feeling"]

a = 0

def test(a):
    while a < len(words):
        print "What does", words[a], "mean?"
        ans = raw_input(">>> ")
        if ans == answers[a]:
            print "Correct!\n"
            a = a + 1
        else: print "That is incorrect. Try again.\n"

test(a)

And to make the test more real, i'd make another list (which would be equal to = range(len(words)) and you could use the random module to spit them out from the list, and also remove them so you don't hit the same one again, at least until you run out of items)

Thanks for all the info guys, except vegaseat, what would be the use of saving the dictionary to a file? Is it for if I wanted to say create a menu that had the option of using one list or another?

Thanks for all the info guys, except vegaseat, what would be the use of saving the dictionary to a file? Is it for if I wanted to say create a menu that had the option of using one list or another?

I think the advantage is you can edit the file to add/subtract as many word/answers you like without having to go into the program and edit the dictionaries directly. I may be incorrect though.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.