can choose the title just by entering its number (the console get_integer(function accepts even if the minimum is greater than zero so that can be used as cancelation value this behavior can be switched off by passing allow_zero=false we can' use enterthat isnothingto mean cancelsince entering nothing means accepting the default def list_dvds(db)start "if len(dbdisplay_limitstart console get_string("list those starting with "[enter=all]""start"print(for title in sorted(dbkey=str lower)if not start or title lower(startswith(start lower())directoryearduration db[titleprint("{title({year}{durationminute{ }by "{director}format(util (duration)**locals())listing all the dvds (or those whose title starts with particular substringis simply matter of iterating over the dbm' items the util (function is simply lambda "if = else " "so here it returns an "sif the duration is not one minute def remove_dvd(db)title find_dvd(db"remove"if title is nonereturn ans console get_bool("remove { }?format(title)"no"if ansdel db[titledb sync(removing dvd is matter of finding the one the user wants to removeasking for confirmationand if we get itdeleting the item from the dbm we have now seen how to open (or createa dbm file using the shelve moduleand how to add items to itedit its itemsiterate over its itemsand remove items unfortunatelythere is flaw in our data design director names are duplicatedand this could easily lead to inconsistenciesfor exampledirector danny devito might be entered as "danny de vitofor one movie and "danny devitofor another one solution would be to have two dbm filesthe main dvd file with title keys and (yeardurationdirector idvaluesand director file with director id ( integerkeys and director name values we avoid this flaw in the next section' sql database version of the program by using two tablesone for dvds and another for directors