Python UnboundLocalError: проблемы с функцией выбора слов из словаря - PullRequest
0 голосов
/ 01 июля 2019

Я написал функцию для выбора одного ключа (= слово) из словаря. Если ключ уже использовался, следует выбрать другой ключ. Это моя функция:

nom_acc = {"qeso":"qes", "os":"os", "sondra":"sondre", "mawizzi":"mawizze", "khewo":"khewe", "alegra":"alegre", "kendra":"kendre", "zhalia":"zhalie", "achrakh":"achrakh", "ador":"ador", "hoggi":"hogge", "soqwi":"soqwe"}
usedWords = []

def wordChoice():
    global usedWords
    print(usedWords) ### DELETE LATER

    word = random.choice(list(nom_acc))     ### randomly pick a key from a dictionary (which is the nominative form)
    print(word) ### DELETE LATER 
    if word in usedWords: 
        print("gotta pick another word") ### DELETE LATER
        wordChoice() 
    else: 
        usedWords.append(word)          
        accusative = nom_acc[word]

    return word, accusative

Функция встроена в основную программу. Когда я запускаю такой код, он выдает сообщение об ошибке, как только выбрано слово, которое уже было использовано: UnboundLocalError: local variable 'accusative' referenced before assignment

Если я добавлю фиктивное значение для слова и винительного падежа, оно будет работать:

    if word in usedWords: 
        print("gotta pick another word") ### DELETE LATER
        word="DUMMY"
        accusative="DUMMY" 

Но я хочу, чтобы из словаря было выбрано другое слово, если оно уже использовалось. Как мне это реализовать?

Ответы [ 2 ]

0 голосов
/ 01 июля 2019

Ошибка возникает из-за проблемы в вашей рекурсивности. Ниже я попытаюсь объяснить проблему в вашей рекурсии. Предположим, это ваш ввод в терминал с вашим текущим кодом:

wordChoice()

Затем интерпретатор Python оценивает выражение, выполняя код в блоке def wordChoice(). Все будет работать гладко, пока ваш if блок Ваш текущий if block is like this:

if word in usedWords: 
    print("gotta pick another word") ### DELETE LATER
    wordChoice() # Python must evaluate this before continuing

Когда ваш word используется, Python доберется до этого нового wordChoice() и оценит это выражение , прежде чем продолжить . Предположим, что при запуске этой второй wordChoice() рандомизированная word не используется, и код достигает вашего блока else.

else: 
    usedWords.append(word)          
    accusative = nom_acc[word]

Здесь тоже нет проблем, все гладко, будет return word, accusative, как вы и хотели. Этот оператор return сообщает Python, как он должен оценивать последний вызванный wordChoice(). Это означает, что он вернется с того места, где остановился в последний раз, когда был вызван wordChoice(), то есть это утверждение if. Так будет и дальше:

if word in usedWords: 
    print("gotta pick another word") ### DELETE LATER
    some_word, some_accusative_value # the interpreter will continue the code from this point
else: 
    usedWords.append(word)          
    accusative = nom_acc[word]

return word, accusative

Это означает, что блок if выполнен и он снова перейдет к return word, accusative, но в рамках этого текущего wordChoice() они не установлены, поскольку этот wordChoice() не дошел до else заявление. Чтобы исправить свою рекурсивность, вы должны return wordChoice(), пока код не выполнится, выполнить оператор else. Ниже приведено правильное решение для того, что вы хотите:

nom_acc = {"qeso":"qes", "os":"os", "sondra":"sondre", "mawizzi":"mawizze", "khewo":"khewe", "alegra":"alegre", "kendra":"kendre", "zhalia":"zhalie", "achrakh":"achrakh", "ador":"ador", "hoggi":"hogge", "soqwi":"soqwe"}

usedWords = []

def wordChoice():
    global usedWords
    print(usedWords) ### DELETE LATER

    word = random.choice(list(nom_acc))     ### randomly pick a key from a dictionary (which is the nominative form)
    print(word) ### DELETE LATER 
    if word in usedWords: 
        print("gotta pick another word") ### DELETE LATER
        return wordChoice() # return correct recursive result 
    else: 
        usedWords.append(word)          
        accusative = nom_acc[word]
        return word, accusative # This return statement should be inside the else statement for clearness
0 голосов
/ 01 июля 2019

Это часть кода, где вызывается функция wordChoice ():

def writeAcc():
    '''Minigame: User has to enter the correct accusative form, after three correct answers he passed'''

    global isPlaying, usedWords
    isPlaying = True

# asking the user to enter the right accusative form of the word        
    print("Please enter the accusative form of the following words\n")

# player passed when he reached 3 correct answers
    right = 0
    while right < 4:
        word, accusative = wordChoice()

        print("Nominative ", word)

        print("Need help? Enter 'y' to see the menu again or press the enter-key to continue.")
        choice = input("\t\t\tChoice: ")
        if choice == 'y':
            continueGame = displayMenu()
            if not continueGame:
                return
            print("Nominative ", word)

        answer=input("Accusative ")
        if answer==accusative:
            right+=1

        print("Guessed right:", right)

        if right < 4 and (len(usedWords) == len(list(nom_acc))):
            print("Sorry you don't seem to have what it takes to learn the accusative.")
            break

    if right == 4:
        print("Congratulations! You passed the first step, you will now enter the next challenge.")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...