Here's some code I used with students last Monday, in Session 8 of 10. They've covered all the Python keywords as of Session 7 but we still need to keep going over all we've learned, seeing how the concepts mesh together.
Actually at this point we haven't looked at the newest keywords async and await, nor yield from as a construct. An epiphany or at least a glue-it-together moment is when we show how a decorator of a function generator may be used to give a context manager. The two versions of the game below work the same way, but the second applies said decorator logic. The script suggests seeing the "context" as a Spooky Castle one enters, there to guess one of the keywords. That's the challenge. Guessing right still results in an exception being raised, but one that's handled by __exit__, whereas failure to "get it right" results in a different exception still in need of handling even after the scope of the with block. Kirby ==== # -*- coding: utf-8 -*- """ Created on Thu Feb 11 04:58:14 2016 @author: Kirby Urner Copyleft MIT License >From the docs: sys.exc_info() This function returns a tuple of three values that give information about the exception that is currently being handled. The information returned is specific both to the current thread and to the current stack frame.... see docs for more """ from keyword import kwlist from random import choice import sys class EscapeVictorious(Exception): pass class KickFromCastle(Exception): pass class Castle: def __init__(self, secret): self.__xyjk = secret self.guesses = 0 self.hints = 0 def __enter__(self): """get the ball rolling""" print("Welcome to Spooky Castle. To Escape, guess the secret keyword") return self # <-- make instance available within scope via 'as' def hint(self): if self.hints == 0: print("The keyword begins with", self.__xyjk[0]) elif self.hints == 1: print("The keyword is", len(self.__xyjk), "letters long.") else: print("You've had your two hints, sorry") self.hints += 1 def query(self): """gradations""" print("So what is the secret keyword then? Guess so far:", self.guesses) ans = input("You may answer (or type 'hint'): ") if ans == self.__xyjk: print("Excellent, we're done here") print("You have won the Copper Key") # <-- RealPlayer One (novel) raise EscapeVictorious("Copper Key") elif self.guesses == 5: print("Uh oh, you're out of guesses, sigh") raise KickFromCastle("We're done!") elif ans == "hint": self.hint() return else: self.guesses += 1 print("No, that's not it.") def __exit__(self, *exception_data): """raise a ruckus""" if exception_data[0] == EscapeVictorious: print("Congratulations!") print("Here is your", exception_data[1]) return True if exception_data[0] == KickFromCastle: print("Better Luck Next Time") print("The keyword was", self.__xyjk) return False if __name__ == "__main__": the_secret = choice(kwlist) try: with Castle(the_secret) as spooky: while True: spooky.query() except: print("Handling: ", sys.exc_info()[0].__name__) print(sys.exc_info()[1]) # <--- triggers __str__ print(type(sys.exc_info()[1])) === # -*- coding: utf-8 -*- """ Created on Thu Feb 11 06:00:49 2016 @author: Kirby Urner Copyleft MIT License """ from contextlib import contextmanager from keyword import kwlist from random import choice import sys class EscapeVictorious(Exception): pass class KickFromCastle(Exception): pass @contextmanager def Castle(secret): try: obj = Game(secret) print("Welcome to Spooky Castle. To Escape, guess the secret keyword") yield obj # <-- make instance available within scope via 'as' except EscapeVictorious as ex: print("Congratulations!") print("Here is your", ex) return None # default, could leave out or pass except KickFromCastle: print("Better Luck Next Time") print("The keyword was", obj._Game__xyjk) raise class Game: def __init__(self, the_secret): self.__xyjk = the_secret self.guesses = 0 self.hints = 0 def hint(self): if self.hints == 0: print("The keyword begins with", self.__xyjk[0]) elif self.hints == 1: print("The keyword is", len(self.__xyjk), "letters long.") else: print("You've had your two hints, sorry") self.hints += 1 def query(self): """gradations""" print("So what is the secret keyword then? Guess so far:", self.guesses) ans = input("You may answer (or type 'hint'): ") if ans == self.__xyjk: print("Excellent, we're done here") print("You have won the Copper Key") # <-- RealPlayer One (novel) raise EscapeVictorious("Copper Key") elif self.guesses == 5: print("Uh oh, you're out of guesses, sigh") raise KickFromCastle("We're done!") elif ans == "hint": self.hint() return else: self.guesses += 1 print("No, that's not it.") if __name__ == "__main__": the_secret = choice(kwlist) try: with Castle(the_secret) as spooky: while True: spooky.query() except KickFromCastle: print("Handling: ", sys.exc_info()[0].__name__) print(sys.exc_info()[1]) # <--- triggers __str__ print(type(sys.exc_info()[1]))
_______________________________________________ Edu-sig mailing list Edu-sig@python.org https://mail.python.org/mailman/listinfo/edu-sig