May-19-2019, 08:28 AM
(This post was last modified: May-19-2019, 08:28 AM by Gribouillis.)
In this second version, we avoid using the
@contextmanager
decorator. Instead, block
is now a class. The advantage of this is that one can subclass block
to create exitable contexts with more data, such as a user session with a user name, a user device, etc__version__ = '2109.05.19' class block: """Block of code context allowing to exit deeply nested loops Usage: with block() as b: ... # somewhere in a nested loop b.exit() ... This type can be subclassed to create exitable contexts with useful data, for example class UserSession(block) def __init__(self, user_name): self.user_name = user_name with UserSession('Doe') as session: ... session.exit() ... """ def __enter__(self): return self def exit(self): raise EndOfBlock(self) def __exit__(self, exc_type, exc_value, ex_tb): if exc_type is EndOfBlock and exc_value.args[0] is self: # exception isn't propagated if __exit__ returns true value return True class EndOfBlock(RuntimeError): """Helper exception type for the block() context""" if __name__ == '__main__': # Example code for blocks class UserSession(block): def __init__(self, user_name): super().__init__() self.user_name = user_name def __enter__(self): print("User {}'s session starting now!".format(self.user_name)) return super().__enter__() def __exit__(self, *args): print('User {} is leaving.'.format(self.user_name)) return super().__exit__(*args) def func(x): """Test function for the block() context""" result = '' with UserSession('Doe') as outer: result += 'A' for i in range(4): result += 'B' if x > 0 and i > 2: outer.exit() result += 'D' with block() as inner: result += 'C' if x == 1: outer.exit() elif x == 2: inner.exit() result += 'E' result += 'F' result += 'G' result += 'H' return result assert func(0) == "ABDCEFBDCEFBDCEFBDCEFGH" assert func(1) == "ABDCH" assert func(2) == "ABDCFBDCFBDCFBH" print('SUCCESS')
Output:User Doe's session starting now!
User Doe is leaving.
User Doe's session starting now!
User Doe is leaving.
User Doe's session starting now!
User Doe is leaving.
SUCCESS