I'm currently taking an online Udemy course in Python programming and we're covering the shelve module. The professor has shown that for some reason, a shelve has no way to know when a mutable object has been changed like this: (he has explained ways around this as well)
import shelve
# Making a bunch of lists to bind to shelves later
blt = ["bacon", "tomato", "lettuce", "bread"]
beans_on_toast = ["beans", "bread"]
scrambled_eggs = ["eggs", "butter", "milk"]
soup = ["tin of soup"]
pasta = ["pasta", "cheese"]
with shelve.open('recipes') as recipes:
# Binding each list to a shelve
recipes['blt'] = blt
recipes['beans on toast'] = beans_on_toast
recipes['scrambled eggs'] = scrambled_eggs
recipes['pasta'] = pasta
recipes['soup'] = soup
# Attempting to append 'butter' and 'tomato' to respective lists
recipes['blt'].append("butter")
recipes['pasta'].append("tomato")
for snack in recipes:
print(snack, recipes[snack])
The output from the for loop shows that the shelves are unchanged and the values 'butter' and 'tomato' weren't appended to their respective shelves.
My online professor has tried to explain why it is so, but I am having trouble understanding. If somebody could try to explain it to me, I would appreciate it.
And if you have the patience, could you explain any terms you might use in your answer that you think I wouldn't understand. I'm still a beginner and Python is the first language I'm learning. Thanks in advance!
Imagine your recipes
shelf as a physical recipe book in your kitchen.
recipes['blt'] = blt
writes a recipe in the book for making a dish like blt
.
Accessing recipes['blt']
makes a dish based on the recipe.
recipes['blt'].append("butter")
makes a dish, and then adds butter to it. The recipe in the book doesn't suddenly involve butter; if you wanted to rewrite the recipe, you would have to do that separately.
That's basically how shelve
works. A Shelf
object is backed by a data file on disk, and each entry in the file contains instructions (in pickle format) for building an object. Accessing the shelf builds an object based on the stored instructions, but changing the object you built won't change the instructions.
If you create the shelf with writeback=True
, then instead of building a new object on each access to an entry, the shelf will cache the built objects and return the same object again if you access the same entry again. It still has no idea when you change anything, but since it's returning the same object, the changes are still present.
When you close a writeback=True
shelf, the shelf will write new pickles for the objects when the shelf is closed. The new pickles will reflect any changes to the objects. This may involve a lot of unnecessary writing, since the shelf still doesn't actually know when you've changed an object, so it has to re-pickle all of them, even the unchanged ones.