Created
July 30, 2022 09:01
-
-
Save moreati/4448f2b5e7dc7a712bdcb8426b258752 to your computer and use it in GitHub Desktop.
Combined Python context manager, iterator, and iterable; with a generator-like send() method
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
EVENS = object() | |
STOP = object() | |
class CM(): | |
def __init__(self, n=10): | |
print('__init__() called') | |
self.n = n | |
self._it = iter(range(n)) | |
self._evens = False | |
self._stop = False | |
@staticmethod | |
def is_odd(n): | |
return n % 2 | |
# Context Manager protocol | |
def __enter__(self): | |
print('__enter__() called') | |
return self | |
# exc_* are None on the happy path, otherwise Return True to suppress | |
def __exit__(self, exc_type, exc_value, exc_traceback): | |
print('__exit__() called') | |
# Iterable protocol | |
def __iter__(self): | |
print('__iter__() called') | |
return self | |
# Iterator protocol | |
def __next__(self): | |
if self._stop: | |
raise StopIteration | |
v = next(self._it) | |
if self._evens and self.is_odd(v): | |
v = next(self._it) | |
return v | |
def send(self, value): | |
if value is EVENS: | |
self._evens = value | |
if value is STOP: | |
self._stop = value | |
if __name__ == '__main__': | |
with CM() as cm: | |
for i in cm: | |
print(i) | |
if i == 1: | |
cm.send(EVENS) | |
if i >= 6: | |
cm.send(STOP) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment