Skip to content

Instantly share code, notes, and snippets.

@jsbueno
Created January 6, 2023 15:59
Show Gist options
  • Save jsbueno/e4378521ead8f9dbb40565fb5cacd0b9 to your computer and use it in GitHub Desktop.
Save jsbueno/e4378521ead8f9dbb40565fb5cacd0b9 to your computer and use it in GitHub Desktop.
Snippets for advanced generator research I used when figuring out an answer for https://stackoverflow.com/questions/74922314/yield-from-vs-yield-in-for-loop
class VerboseItBase:
def __new__(cls, gen, method):
if method == "from":
cls = VerboseItFrom
elif method == "explicit":
cls = VerboseItExplicit
return super().__new__(cls)
def __init__(self, gen, method):
self.gen = gen
self.method = method
def __iter__(self):
print("verbose iter called for 'classic'")
try:
for item in self.gen:
yield item
except GeneratorExit:
print("generator exit thrown in intermediate gen. 'classic'")
raise
def close(self):
print("close in intermediate iterator called")
# Explictly do not forward close for testing purposes:
# self.gen.close()
def __del__(self):
print("intermediate iterator __del__")
try:
super().__del__()
except AttributeError:
pass
VerboseIt = VerboseItBase
class VerboseItExplicit(VerboseItBase):
def __iter__(self):
print("verbose iter called for 'explict'")
return self
def throw(self, *args):
print(args)
def __next__(self):
print("intermediate __next__ called")
return next(self.gen)
class VerboseItFrom(VerboseItBase):
def __iter__(self):
print("verbose iter called for 'yield from'")
try:
yield from self.gen
except GeneratorExit:
print("generator exit thrown in intermediate gen. 'from'")
raise
return
class Test:
def __init__(self, gen, method):
self.gen = gen
self.method = method
def __iter__(self):
return iter(VerboseIt(self.gen, self.method))
first = lambda i: next(iter(i))
a = Test((i for i in range(3)), "")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment