# The purpose of this example is to demonstrate what is a dictionary in Python. # This will also cover: # functions, # switch, and # writing to text files. # This function adds a birthday to the list of birthdays. # Simple, isn't it? # There's one flaw, though: In case we've already stored the data for that # person, it will overwrite that data. def add_birthday(person, day, birthdays): birthdays[person] = day # This does the same as the previous function, but checks if we already have # the birthday of that person remembered and warns us in that case. # Practice: This function is not used in this example, only defined. # Could you change the code so that it is used instead of # the default "add_birthday" function? def add_birthday_safer(person, day, birthdays): if birthdays.has_key(person): print "You've already entered " + person + "'s birthday as:", print birthdays[person] print "Would you like to overwrite that with " + day + " (y/n)?" response = raw_input("Response: ") # Practice: Add some more possible answers (like with capital letters) if response == "n" or response == "no": # "return" marks the end of the function return else: birthdays[person] = day # To change an existing record: just overwrite whatever was there before! # It will simply add a new record if there wasn't a person with the given name, # and that is fine. Because of that, we don't have to check if the record exists. def change_birthday(person, day, birthdays): birthdays[person] = day # This function deletes a birthday. def forget_birthday(person, birthdays): if birthdays.has_key(person): del birthdays[person] else: print "No such person." # This function check if it's anyone's birthday today. def check_birthdays(birthdays): # this will get us the today's date in the form ddmm, the same # as we enter it. We don't need the year, most people have birthdays # each year. :) # Practice: Who doesn't? today = time.strftime("%d%m") none_today = True for person in birthdays: bday = birthdays[person] # How do we know which birthday is it? # Easy: current year - birth year. # time.strftime("%Y") gets us the current year, and the birth year # is written in "bday" variable, from 4th index to the last. # Since both are written as strings, we have to turn them to numbers # before we can subtract them, and we do that by passing them to the int() # function. When they are subtracted, turn the result back into a string, # by passing it to the str() function. which = str( int(time.strftime("%Y")) - int(bday[4:]) ) if bday[0:4] == today: print "It's " + person + "'s " + which + ". birthday, yay!" none_today = False if none_today: print "No birthdays today." # Practice: Could we make the output of this function nicer? # For example, change it to the form of dd.mm.yyyy instead of ddmmyyy ? def print_birthdays(birthdays): for person, day in birthdays.items(): print person + " was born on " + day + "." if len(birthdays.items()) == 0: print "There are no birthdays memorised." # This function takes a name and finds that person's birthday. def find_birthday(name, birthdays): if birthdays.has_key(name): print name + "'s birthday is on: " + birthdays[name] else: print "You never entered " + name + "'s birthday!" def save_to_file(filename, bdays): # Warning: If there already exists a file with this name, opening it in "w"rite # mode will delete the existing file and create a blank one! # Opening in "a"ppend mode adds everything to the end of an existing file, # but we won't use it here. # Practice: Try writing a program which appends to text files to see how it works. f = open(filename, "w") # Practice: What does str(bdays) give us? Try it on a dictionary variable! text = str(bdays) f.write(text) f.close() def load_from_file(filename): my_file = open(filename, "r") text_from_file = my_file.read() # eval() takes text and then runs it as if it were Python code. # For us, it will turn a textual representation of a dictionary to a functional # Python dictionary. bday_dictionary = eval(text_from_file) # Return that to whoever called load_from_file() in the first place. return bday_dictionary # This function checks whether the string you entered is actually a date. # What are the things we check for? # What could also be checked? Is it possible to enter a future date now? def validate_date(user_input): if len(user_input) != 8: return False try: int(user_input) except: return False if int(user_input) < 0: return False if int(user_input[0:2]) > 31: return False if int(user_input[2:4]) > 12: return False if int(user_input[4:8]) > int(time.strftime("%Y")): return False return True # This function displays the menu which you see when you run the program. def menu(): # Here we will store all the birthday data. Notice the {} - that's how we # define that a variable is a dictionary. # This will get us an empty dictionary, and we'll see how to fill it # with data in a moment. birthdays = {} # We'll display the menu in an infinite loop. # The condition in while() will always be true, since it's, well.. True. # The entire function, though, will end when the user enters "7". while (True): # Print thirty # and move to a new line. print "#" * 60 + "\n" print "Please choose from the following: " print "\t1. Print all birthdays we have remembered." print "\t2. Check if someone's birthday is today." print "\t3. Find someone's birthday." print "\t4. Add a new birthday." print "\t5. Change the data for an existing birthday." print "\t6. Delete an existing birthday." print "\t7. Write all birthdays to a file." print "\t8. Load birthdays from a file." print "\t9. Exit." choice = raw_input("Your choice: ") if choice == "1": print_birthdays(birthdays) elif choice == "2": check_birthdays(birthdays) elif choice == "3": print "Enter your friend's name: " name = raw_input() find_birthday(name, birthdays) elif choice == "4": print "Enter your friend's name: " name = raw_input() print "Enter " + name + "'s birthday (ddmmyyyy): " birthday = raw_input() if validate_date(birthday): add_birthday(name, birthday, birthdays) else: print "That is not a valid birthday." elif choice == "5": print "Enter your friend's name: " name = raw_input() print "Enter " + name + "'s birthday (ddmmyyyy): " birthday = raw_input() if validate_date(birthday): change_birthday(name, birthday, birthdays) else: print "That is not a valid birthday." elif choice == "6": print "Enter your friend's name: " name = raw_input() forget_birthday(name, birthdays) elif choice == "7": print "Enter the name of the file in which to store: " filename = raw_input() print "Location of that file (can be blank): " filename = raw_input() + filename save_to_file(filename, birthdays) elif choice == "8": print "Name of the file with stored birthdays: " filename = raw_input() print "Location of that file (can be blank): " filename = raw_input() + filename # Warning! Doing this will overwrite anything we're put in our dictionary # so far with that is saved in that file. birthdays = load_from_file(filename) # Practice: Currently, there's no way for a user to load data from two # different files at once. It would be possible to ask for two filenames # a write a function which would take those two filenames, read from both # files and combine their content into one dictionary. # A hint: dictionaries have a method called "update", # look it up to see what it does! elif choice == "9": return else: print "That is not a valid option!" raw_input("Press enter to continue...") # This is where our program starts executing. It enters the menu() function and # runs it until you choose to leave. print "Welcome to the birthday reminder." import time menu() print "Exiting the birthday reminder... Bye!"