<div dir="ltr"><div><div><div>What I like about the appended module is it exercises constructs in a somewhat meaningless fashion that nevertheless has a story, a strong metaphor.  We're in a spooky castle and want to leave having guessed a Python keyword, hidden in  <span style="font-family:monospace,monospace">self.__xyjk </span>during initialization.<br><br>If we guess it right in five tries, an exception is raised, but one signalling we're victorious, and so the __exit__ method handles it in a congratulatory manner and returns True, and we're released from the castle without fuss or bother.<br><br></div>If we can't guess it in five tries, even after two hints, then the exception is a kick in the pants; we're booted out with an unhandled exception (return False).  <br><br>The outer handler takes care of <span style="font-family:monospace,monospace">KickFromCastle </span>in that case.  The print() statements tell the story.<br><br>All pretty pointless... except to those learning Python.<br><br></div>Tonight I interleaved the code below with a more serious-looking use of context managers in a Jupyter Notebook.<br><br><a href="http://bit.ly/2aiFaIA">http://bit.ly/2aiFaIA</a>  <--- looks through nbviewer (Jupyter Notebook viewer) at one of my Github JNs (just another web page)<br><br></div>Kirby<br><br><div><div><div><br>==<span style="font-family:monospace,monospace"><br><br>from keyword import kwlist<br>from random import choice<br>import sys<br><br>class EscapeVictorious(Exception):<br>    pass<br><br>class KickFromCastle(Exception):<br>    pass<br><br>class Castle:<br>    <br>    def __init__(self, secret):<br>        self.__xyjk = secret<br>        self.guesses = 0<br>        self.hints = 0<br>        <br>    def __enter__(self):<br>        """get the ball rolling"""<br>        print("Welcome to Spooky Castle. To Escape, " <br>        "guess the secret keyword")<br>        return self  # <-- make me available within scope via 'as'<br> <br>    def hint(self):<br>        if self.hints == 0:<br>            print("The keyword begins with", self.__xyjk[0])<br>        elif self.hints == 1:<br>            print("The keyword is", len(self.__xyjk), "letters long.")<br>        else:<br>            print("You've had your two hints, sorry")<br>        self.hints += 1<br>        <br>    def query(self):<br>        """gradations"""<br>        print("So what is the secret keyword then? "<br>              " Guess so far:", self.guesses)<br>        ans = input("You may answer (or type 'hint'): ")<br>        if ans == self.__xyjk:<br>            print("Excellent, we're done here")<br>            print("You have won the Copper Key") # <-- RealPlayer One (novel)<br>            raise EscapeVictorious("Copper Key")<br>        elif self.guesses == 5:<br>            print("Uh oh, you're out of guesses, sigh")<br>            raise KickFromCastle("We're done!")<br>        elif ans == "hint":<br>            self.hint()<br>            return<br>        else:<br>            self.guesses += 1<br>            print("No, that's not it.")<br>            <br>    def __exit__(self, *exception_data):<br>        """raise a ruckus"""<br>        if exception_data[0] == EscapeVictorious:<br>            print("Congratulations!")<br>            print("Here is your", exception_data[1])<br>            return True<br>        if exception_data[0] == KickFromCastle:<br>            print("Better Luck Next Time")<br>            print("The keyword was", self.__xyjk)<br>            return False<br>        <br>if __name__ == "__main__":<br>    the_secret = choice(kwlist)<br>    try:<br>        with Castle(the_secret) as spooky:<br>            while True:<br>                spooky.query()<br>    except:<br>        print("Handling: ", sys.exc_info()[0].__name__)<br>        print(sys.exc_info()[1])  # <--- triggers __str__<br>        print(type(sys.exc_info()[1]))</span><br>        <br></div></div></div></div>