user4630914
user4630914

Reputation:

Appending a value to a key in Python?

if savescores == "y":
        name = raw_input("Enter your name.")
        datfile = filename[0:-4] + ".dat"
        highscores = shelve.open(datfile)
        try:
            highscores[name].append(score)
        except:
            highscores[name] = [score]

If this specific player already has a score, I want to append the new score to the scores he already has, but apparently this doesn't work, because it doesn't change his score at all.

Upvotes: 2

Views: 1121

Answers (1)

Steven Rumbalski
Steven Rumbalski

Reputation: 45542

The Shelf object does not detect changes to mutable objects in your shelf. It only detects assignment.

To fix this, open your shelf with writeback=True and make sure to close when you are done. (You can also sync every so often to lower memory usage of the cache.)

Relevant docs from shelve.open:

Because of Python semantics, a shelf cannot know when a mutable persistent-dictionary entry is modified. By default modified objects are written only when assigned to the shelf (see Example). If the optional writeback parameter is set to True, all entries accessed are also cached in memory, and written back on sync() and close(); this can make it handier to mutate mutable entries in the persistent dictionary, but, if many entries are accessed, it can consume vast amounts of memory for the cache, and it can make the close operation very slow since all accessed entries are written back (there is no way to determine which accessed entries are mutable, nor which ones were actually mutated).

Note that you can skip opening with writeback=True to save memory, but your code will be more verbose as shown in this example from the shelve docs.

# as d was opened WITHOUT writeback=True, beware:
d['xx'] = [0, 1, 2]    # this works as expected, but...
d['xx'].append(3)      # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!

# having opened d without writeback=True, you need to code carefully:
temp = d['xx']      # extracts the copy
temp.append(5)      # mutates the copy
d['xx'] = temp      # stores the copy right back, to persist it

# or, d=shelve.open(filename,writeback=True) would let you just code
# d['xx'].append(5) and have it work as expected, BUT it would also
# consume more memory and make the d.close() operation slower.

d.close()       # close it

By the way, this code

try:
    highscores[name].append(score)
except:
    highscores[name] = [score]

is more concisely expressed as

highscores.setdefault(name, []).append(score)

Upvotes: 6

Related Questions