Python: объект «NoneType» не имеет атрибута «get_username»

Я работаю над программой палача, в которой также есть объекты учетных записей пользователей. Игрок может войти в систему, создать новую учетную запись или просмотреть сведения об учетной записи, и все это работает нормально перед игрой. После завершения игры обновляются выигрыши и проигрыши пользователя. Перед выходом из программы, если я пытаюсь просмотреть счет (функция viewAcc) я получаю ошибку:

'NoneType' object has no attribute 'get_username'.

Когда я снова запускаю программу, я могу войти в учетную запись, но когда я просматриваю информацию об учетной записи, выигрыши и проигрыши не обновляются. Любая помощь будет оценена по достоинству, я должен сдать это для класса примерно через 8 часов.

Вот код класса:

class Account:
    def __init__(self, username, password, name, email, win, loss):
        self.__username = username
        self.__password = password
        self.__name = name
        self.__email = email
        self.__win = int(win)
        self.__loss = int(loss)

    def set_username (self, username):
        self.__username = username

    def set_password (self, password):
        self.__password = password

    def set_name (self, name):
        self.__name = name

    def set_email (self, email):
        self.__email = email

    def set_win (self, win):
        self.__win = win

    def set_loss (self, loss):
        self.__loss = loss

    def get_username (self):
        return self.__username

    def get_password (self):
        return self.__password

    def get_name (self):
        return self.__name

    def get_email (self):
        return self.__email

    def get_win (self):
        return self.__win

    def get_loss (self):
        return self.__loss

И вот код моей программы:

import random
import os
import Account
import pickle
import sys
#List of images for different for different stages of being hanged
STAGES = [
'''
      ___________
     |/         |
     |          |
     |         
     |         
     |          
     |         
     |
     |
     |
_____|______
'''
,
'''
      ___________
     |/         |
     |          |
     |        (o_o)
     |         
     |          
     |         
     |
     |
     |
_____|______
'''
,
'''
      ___________
     |/         |
     |          |
     |        (o_o)
     |          | 
     |          |
     |         
     |
     |
     |
_____|______
'''
,
'''
      ___________
     |/         |
     |          |
     |        (o_o)
     |          |/ 
     |          |
     |          
     |
     |
     |
_____|______
'''
,
'''
      ___________
     |/         |
     |          |
     |        (o_o)
     |         \|/ 
     |          |
     |           
     |
     |
     |
_____|______
'''
,
'''
      ___________
     |/         |
     |          |
     |        (o_o)
     |         \|/ 
     |          |
     |         / 
     |
     |
     |
_____|______
'''
,
'''
    YOU DEAD!!!
      ___________
     |/         |
     |          |
     |        (X_X)
     |         \|/ 
     |          |
     |         / \ 
     |
     |
     |
_____|______
'''
]

#used to validate user input
ALPHABET = ['abcdefghijklmnopqrstuvwxyz']

#Declares lists of different sized words
fourWords = ['ties', 'shoe', 'wall', 'dime', 'pens', 'lips', 'toys', 'from', 'your', 'will', 'have', 'long', 'clam', 'crow', 'duck', 'dove', 'fish', 'gull', 'fowl', 'frog', 'hare', 'hair', 'hawk', 'deer', 'bull', 'bird', 'bear', 'bass', 'foal', 'moth', 'back', 'baby']
fiveWords = ['jazzy', 'faker', 'alien', 'aline', 'allot', 'alias', 'alert', 'intro', 'inlet', 'erase', 'error', 'onion', 'least', 'liner', 'linen', 'lions', 'loose', 'loner', 'lists', 'nasal', 'lunar', 'louse', 'oasis', 'nurse', 'notes', 'noose', 'otter', 'reset', 'rerun', 'ratio', 'resin', 'reuse', 'retro', 'rinse', 'roast', 'roots', 'saint', 'salad', 'ruins']
sixwords =  ['baboon', 'python',]


def main():
    #Gets menu choice from user
    choice = menu()

    #Initializes dictionary of user accounts from file
    accDct = loadAcc()

    #initializes user's account
    user = Account.Account("", "", "", "", 0, 0)

    while choice != 0:
        if choice == 1:
           user = play(user)
        if choice == 2:
            createAcc(accDct)
        if choice == 3:
           user = logIn(accDct)
        if choice == 4:
            viewAcc(user)
        choice = menu()

    saveAcc(accDct)

#Plays the game
def play(user):

    os.system("cls") #Clears screen
    hangman = 0      #Used as index for stage view
    done = False    #Used to signal when game is finished
    guessed = ['']   #Holds letters already guessed

    #Gets the game word lenght from the user
    difficulty = int(input("Chose Difficulty/Word Length:\n"\
                           "1. Easy: Four Letter Word\n"\
                           "2. Medium: Five Letter Word\n"\
                           "3. Hard: Six Letter Word\n"\
                           "Choice: "))
    #Validates input                 
    while difficulty < 1 or difficulty > 3:
        difficulty = int(input("Invalid menu choice.\n"\
                               "Reenter Choice(1-3): "))

    #Gets a random word from a different list depending on difficulty
    if difficulty == 1:
        word = random.choice(fourWords)
    if difficulty == 2:
        word = random.choice(fiveWords)
    if difficulty == 3:
        word = random.choice(sixWords)

    viewWord = list('_'*len(word))
    letters = list(word)

    while done == False:

        os.system("cls")

        print(STAGES[hangman])
        for i in range(len(word)):
            sys.stdout.write(viewWord[i])
            sys.stdout.write(" ")
        print()
        print("Guessed Letters: ")
        for i in range(len(guessed)):
            sys.stdout.write(guessed[i])
        print()

        guess = str(input("Enter guess: "))
        guess = guess.lower()

        while guess in guessed:
            guess = str(input("Already guessed that letter.\n"\
                              "Enter another guess: "))

        while len(guess) != 1:
            guess = str(input("Guess must be ONE letter.\n"\
                              "Enter another guess: "))

        while guess not in ALPHABET[0]:
            guess = str(input("Guess must be a letter.\n"\
                     "Enter another guess: "))

        if guess not in letters:
            hangman+=1

        for i in range(len(word)):
            if guess in letters[i]:
                viewWord[i] = guess

        guessed += guess

        if '_' not in viewWord:
            print ("Congratulations! You correctly guessed",word)
            done = True

            win = user.get_win()
            win += 1
            username = user.get_username()
            password = user.get_password()
            name = user.get_name()
            email = user.get_email()
            loss = user.get_loss()
            user = Account.Account(username, password, name, email, win, loss)

        if hangman == 6:
            os.system("cls")
            print()
            print(STAGES[hangman])
            print("You couldn't guess the word",word.upper(),"before being hanged.")
            print("Sorry, you lose.")
            done = True

            loss = user.get_loss()
            loss += 1
            username = user.get_username()
            password = user.get_password()
            name = user.get_name()
            email = user.get_email()
            win = user.get_win()
            user = Account.Account(username, password, name, email, win, loss)






#Loads user accounts from file
def loadAcc():
    try:
        iFile = open('userAccounts.txt', 'rb')

        accDct = pickle.load(iFile)

        iFile.close

    except IOError:
        accDct = {}

    return accDct

#Displays the menu        
def menu():
    os.system('cls')
    print("Welcome to Karl-Heinz's Hangman")
    choice = int(input("1. Play Hangman\n"\
                       "2. Create Account\n"\
                       "3. Log In\n"\
                       "4. View Account Details\n"\
                       "0. Quit Program\n"\
                       "Choice: "))
    while choice < 0 or choice > 4:
        choice = int(input("Invalid Menu Choice.\n"\
                           "Reenter Choice: "))

    return choice

#Logs user in to existing account      
def logIn(accDct):
    os.system('cls')
    user = Account.Account("","","","",0,0)
    username = str(input("Enter Username(case sensitive): "))
    if username not in accDct:
        print("Account does not exist")
        os.system("pause")
        return user

    temp = Account.Account("","","","",0,0)
    temp = accDct[username]

    password = str(input("Enter Password(case sensitive): "))
    if password != temp.get_password():
        print("Incorrect password.")
        os.system("pause")
        return user

    user = accDct[username]
    return user


#Creates a new account and a new account file if one doesn't exist
def createAcc(accDct):
    os.system('cls')
    print("Enter account info:")
    username = str(input("UserName: "))

    if username in accDct:
        print("Account already exists.")
        os.system("pause")
        return

    password = str(input("Password: "))
    name = str(input("Name: "))
    email = str(input("Email: "))
    wins = 0
    loss = 0

    tempuser = Account.Account(username, password, name, email, wins, loss)

    accDct[username] = tempuser

    print("Account created.")
    os.system("pause")

def viewAcc(user):
    os.system('cls')



    print("Account Details: ")
    print("Username: ",user.get_username())
    print("Name: ",user.get_name())
    print("Email: ",user.get_email())
    print("Wins: ",user.get_win())
    print("Losses: ",user.get_loss())

    os.system("pause")






#Saves accounts dictionary to file
def saveAcc(accDct):    
    oFile = open("userAccounts.txt", "wb")

    pickle.dump(accDct, oFile)

    oFile.close()


main()

Любая помощь приветствуется.


person KGil    schedule 25.04.2013    source источник
comment
Вы должны использовать одно ведущее подчеркивание для частных переменных, двойное - для искажения имен.   -  person jamylak    schedule 25.04.2013
comment
Отступ в файле Accont неверный, проверьте в реальном файле.   -  person jvallver    schedule 25.04.2013
comment
Разве это не то, что нужно для код-ревью?   -  person Dr. Jan-Philip Gehrcke    schedule 25.04.2013


Ответы (3)


В вашей функции play() нет инструкции return, что означает, что она возвращает None в качестве возвращаемого значения. Вот как вы получаете None в свою переменную user в main(). Добавьте оператор return в свою функцию play(), и все будет в порядке.

person rmunn    schedule 25.04.2013
comment
Ого, три ответа одновременно! - person rmunn; 25.04.2013
comment
Вау, я не знаю, как я пропустил это. Недостаток сна, я полагаю. Огромное спасибо. - person KGil; 25.04.2013

Вы создаете новые Account экземпляры в play, но никогда их не возвращаете. Затем переменной user в main назначается None, потому что play никогда ничего не возвращает.

Верните user из play, когда закончите:

def play(user):
    # ....

    return user
person Martijn Pieters    schedule 25.04.2013

Функция play не возвращает экземпляр Account. затем он возвращает None. Если вы вызываете функцию play перед функцией viewAcc, тогда пользователь равен None

person jvallver    schedule 25.04.2013