Python绝对是初学者,第7章挑战2

时间:2013-07-31 12:15:45

标签: python pickle

我一直在阅读本书中的练习,但我遇到了一些障碍。挑战在于:

“改进Trivia Challenge游戏,使其在文件中保留一个高分列表。该程序应记录玩家的名字和分数。使用腌制对象存储高分。”

我已成功将分数保存到列表中,然后将此列表附加到dat文件中。但是,当我尝试查看分数/读取文件时,它似乎只显示输入的第一个分数。我看了一下bat文件,它似乎正确地倾倒了列表,所以我想知道我是否弄乱了检索部分?

感谢您阅读

这是代码(BEFORE):

def high_score():
    """Records a player's score"""
    high_scores = []

    #add a score
    name = input("What is your name? ")
    player_score = int(input("What is your score? "))
    entry = (name, player_score)
    high_scores.append(entry)
    high_scores.sort(reverse=True)
    high_scores = high_scores[:5]       # keep only top five

    # Open a new file to store the pickled list
    f = open("pickles1.dat", "ab")
    pickle.dump(high_scores, f)
    f.close()

    choice = None
    while choice !="0":
        print(
            """
            0 - Quit
            1 - Show high scores
            """
            )
        choice = input("choice: ")
        print()

        # exit
        if choice == "0":
            print("Goodbye")

        # show a score
        if choice == "1":
            f = open("pickles1.dat", "rb")
            show_scores = pickle.load(f)
            print(show_scores)
            f.close()

    input("\n\nPress enter to exit.")

解决方案(之后):

def high_score():
"""Records a player's score"""

# no previous high score file
try:
    with open("pickles1.dat", "rb") as f:
        high_scores = pickle.load(f)
except EOFError:
    high_scores = []

#add a score // Do current stuff for adding a new score...
name = input("What is your name? ")
player_score = int(input("What is your score? "))
entry = (name, player_score)
high_scores.append(entry)
high_scores.sort(reverse=True)
high_scores = high_scores[:5]       # keep only top five

# dump scores
with open("pickles1.dat", "wb") as f:
    pickle.dump(high_scores, f)

2 个答案:

答案 0 :(得分:2)

f = open("pickles1.dat", "ab")
#                         ^

您已在“追加”模式下打开文件。那很好,但它可能没有做你想要的。每次尝试将数据保存到这样的文件时,它都会被添加到最后。您必须阅读您编写的每一个项目以获得最近编写的内容。相反,在写入模式下打开文件。这样,每次都会替换其内容:

f = open("pickles1.dat", "wb")

或者,您可以使用追加,但您必须反复调用pickle.load()以查看所有已写入的值。这是伪代码,首先是前者,"w"

scores = pickle.load(open('scores.dat', 'rb'))
scores.append(123)
pickle.dump(scores, open('scores.dat', 'wb'))

和后者:

pickle.dump(123, open('scores.dat', 'ab'))
scores = []
with open('scores.dat', 'rb') as f:
    while True:
        try:
            scores.append(pickle.load(f))
        except EOFError:
            break

我希望你能明白为什么我认为前者(覆盖)更好;它简单得多。

答案 1 :(得分:1)

您的代码存在一些问题。 @TokenMacGuy已经确定了一个,即您将结果附加到输出文件的末尾,而不是覆盖以前的值。

但是有一个更基本的问题。当您运行highscores功能时,您总是从空的高分列表开始。然后,您可以为其添加一个分数,然后将其写出来。使用这种结构,您一次不会写入多个分数(因此,即使您要回读正确编写的内容,它也只会获得1个元素的列表。)

在添加新值之前,您需要添加一些代码以在函数开头加载文件中的高分列表。当没有以前的高分文件时,您需要设置一个特殊情况,但对于try / except块并不是太困难。这是一些缩写代码:

def high_score():
    try:
        with open("pickles1.dat", "rb") as f:
            high_scores = pickle.load(f)
    except FileNotFoundError:
        high_scores = []

    # do current stuff for adding a new score, sorting and slicing

    with open("pickles1.dat", "wb") as f: # "wb" mode overwrites the previous file
        pickle.dump(high_scores, f)

    # do other stuff, like displaying high_scores

此方法的一个好处是,如果用户要求,您无需稍后重新读取该文件,因为high_scores列表已经是最新的。