self pay job pay real instance data def __getattr__(selfattr)if attr ='tax'return self pay elseraise attributeerror(on person attr computed on access other unknown names def info(self)return self nameself jobself payself tax this revision has new tax rate ( percent)introduces __getattr__ qualification overload methodand deletes the original tax method because this new version of the class is re-imported when its existing instances are loaded from the shelve filethey acquire the new behavior automatically--their tax attribute references are now intercepted and computed when accessedc:\pp \dbasepython import shelve dbase shelve open('cast'reopen shelve print(list(dbase keys())both objects are here ['bob''emily'print(dbase['emily']print(dbase['bob'taxno need to call tax( because the class has changedtax is now simply qualifiednot called in additionbecause the tax rate was changed in the classbob pays more this time around of coursethis example is artificialbut when used wellthis separation of classes and persistent instances can eliminate many traditional database update programs in most casesyou can simply change the classnot each stored instancefor new behavior shelve constraints although shelves are generally straightforward to usethere are few rough edges worth knowing about keys must be strings (and strfirstalthough they can store arbitrary objectskeys must still be strings the following failsunless you convert the integer to the string manually firstdbase[ value failsbut str( will work this is different from in-memory dictionarieswhich allow any immutable object to be used as keyand derives from the shelve' use of dbm files internally as we've seenshelve files