# fdemo.py # Lillian Lee (LJL2), Steve Marschner (srm2) # The idea to have an if-statement based on "he loves me", # which was the inspiration for this demo, is due to J. Kleinberg # Feb 19, 2014 """Module that when run, simulates the 'he loves me' flower ritual. This demo was developed for the purposes of demonstrating if-statements and conditional expressions; see the functions pluck(f), pluck1(f) and pluck2(f). You can put any of these plucking functions into run_flower() and see what happens. It also happens to demonstrate primitive versions of useful stuff that we haven't talked about (yet): defining your own class of objects, prompting a user for input, and doing something repeatedly via while-loops. A number of design choices were made in writing this code, simple as it may seem, and several alternatives are possible.""" import random class Flower(object): """An instance is a flower. Flowers have two attributes. We describe these below by giving the 'class invariants' in comments. Programmers are assumed to write code that maintains the class invariants; they are constraints that are assumed to hold before and after code is executed. num_petals [int]: the number of petals. >= 0. loves_me_not: True if and only if the next petal to pluck corresponds to "he loves me" (vs. "he loves me not"), assuming there is at least one more petal. BUT, if there are no more petals, the value of loves_me_not is None.""" # max number of petals a flower can have (since lecture is short) MAX_PETALS = 5 # METHODS def __init__(self): """Initializer: A new flower() with num_petals set to a random int in [1,MAX_PETALS], and he_loves_me set to True.""" self.num_petals = random.randrange(1, Flower.MAX_PETALS+1) self.he_loves_me = True def print_petals(self): """Returns: String showing all the flower's petals as vertical bars. Sample outputs are: '|||' '||' '' """ return '|' * self.num_petals def pluck(f): """Pluck a petal in the 'he loves me' ritual Prints out the appropriate 'he loves me' or 'he loves me not' message, and then removes a petal. An exclamation point is added to the printout if this was the last petal. Precondition: f is a Flower with at least one petal. Prints out a warning and exits if f has no petals""" # This implementation uses if-statements with complex booleans. if f.num_petals == 0: print 'no more petals' return # execution stops here # print out the right thing if f.he_loves_me and f.num_petals > 1: print "he loves me" elif f.he_loves_me and f.num_petals == 1: print "he loves me!" elif not f.he_loves_me and f.num_petals > 1: print "he loves me not" else: print "he loves me not!" # reduce the number of petals f.num_petals = f.num_petals - 1 # "flip" the he_loves_me "bool" if f.num_petals > 0: f.he_loves_me = not f.he_loves_me else: # no more petals left f.he_loves_me = None def pluck1(f): """Pluck a petal in the 'he loves me' ritual Prints out the appropriate 'he loves me' or 'he loves me not' message, and then removes a petal. An exclamation point is added to the printout if this was the last petal. Precondition: f is a Flower with at least one petal. Prints out a warning and exits if f has no petals""" #This implementation uses nested if-statements. if f.num_petals == 0: print 'no more petals' return if f.he_loves_me: if f.num_petals > 1: print "he loves me" else: print "he loves me!" else: # he doesn't love me OR he_loves_me is None if f.num_petals > 1: print "he loves me not" else: print "he loves me not!" # maintain class invariants on f.he_loves_me and f.num_petals f.num_petals = f.num_petals - 1 f.he_loves_me = not f.he_loves_me if f.num_petals > 0 else None def pluck2(f): """Pluck a petal in the 'he loves me' ritual Prints out the appropriate 'he loves me' or 'he loves me not' message, and then removes a petal. An exclamation point is added to the printout if this was the last petal. Precondition: f is a Flower with at least one petal. Prints out a warning and exits if f has no petals""" #this implementation uses conditional expressions if f.num_petals == 0: print 'no more petals' return if f.he_loves_me: print "he loves me" + ('' if f.num_petals > 1 else '!') else: print "he loves me not" + ('' if f.num_petals > 1 else '!') # maintain class invariants on f.he_loves_me and f.num_petals f.num_petals = f.num_petals - 1 f.he_loves_me = not f.he_loves_me if f.num_petals > 0 else None def pluck3(f): """Pluck a petal in the 'he loves me' ritual Prints out the appropriate 'he loves me' or 'he loves me not' message, and then removes a petal. An exclamation point is added to the printout if this was the last petal. Precondition: f is a Flower with at least one petal. Prints out a warning and exits if f has no petals""" #this implementation uses a "one-liner" conditional expressions if f.num_petals == 0: print 'no more petals' return # execution halts here if this if clause were entered print ("he loves me" + ("" if f.he_loves_me else " not") + ("" if f.num_petals > 1 else "!")) # maintain class invariants on f.he_loves_me and f.num_petals f.num_petals = f.num_petals - 1 f.he_loves_me = not f.he_loves_me if f.num_petals > 0 else None if __name__ == '__main__': """Simulate the 'he loves me' ritual with the user.""" # Uses a while loop. print "\nHope you had a happy Valentine's Day!" raw_input("Press 'return' to pick a flower. ") f = Flower() # don't need flower.Flower() because inside flower.py print "New flower picked. " # omit for more surprise: + f.print_petals() while f.num_petals > 0: raw_input('Press "return" to pluck a petal. ') pluck(f) # omitting the line below so as to not spoil the surprise #nprint f.print_petals()