Skip to content Skip to sidebar Skip to footer

How To Write Python Generator Function That Never Yields Anything

I want to write a Python generator function that never actually yields anything. Basically it's a 'do-nothing' drop-in that can be used by other code which expects to call a gener

Solution 1:

Another way is

defempty_generator():
    returnyield

Not really "more expressive", but shorter. :)

Note that iter([]) or simply [] will do as well.

Solution 2:

An even shorter solution:

def empty_generator():
  yieldfrom []

Solution 3:

For maximum readability and maintainability, I would prioritize a construct which goes at the top of the function. So either

  1. your original if False: yield construct, but hoisted to the very first line, or
  2. a separate decorator which adds generator behavior to a non-generator callable.

(That's assuming you didn't just need a callable which did something and then returned an empty iterable/iterator. If so then you could just use a regular function and return ()/return iter(()) at the end.)

Imagine the reader of your code sees:

defname_fitting_what_the_function_does():
    # We need this function to be an empty generator:ifFalse: yield# that crucial stuff that this function exists to do

Having this at the top immediately cues in every reader of this function to this detail, which affects the whole function - affects the expectations and interpretations of this function's behavior and usage.

How long is your function body? More than a couple lines? Then as a reader, I will feel righteous fury and condemnation towards the author if I don't get a cue that this function is a generator until the very end, because I will probably have spent significant mental cost weaving a model in my head based on the assumption that this is a regular function - the first yield in a generator should ideally be immediately visible, when you don't even know to look for it.

Also, in a function longer than a few lines, a construct at the very beginning of the function is more trustworthy - I can trust that anyone who has looked at a function has probably seen its first line every time they looked at it. That means a higher chance that if that line was mistaken or broken, someone would have spotted it. That means I can be less vigilant for the possibility that this whole thing is actually broken but being used in a way that makes the breakage non-obvious.

If you're working with people who are sufficiently fluently familiar with the workings of Python, you could even leave off that comment, because to someone who immediately remembers that yield is what makes Python turn a function into a generator, it is obvious that this is the effect, and probably the intent since there is no other reason for correct code to have a non-executed yield.

Alternatively, you could go the decorator route:

@generator_that_yields_nothingdefname_fitting_what_the_function_does():
    # that crucial stuff for which this existsdefgenerator_that_yields_nothing(wrapped):
    @functools.wraps(wrapped)defwrapper_generator():
        ifFalse: yield
        wrapped()
    return wrapper_generator

Post a Comment for "How To Write Python Generator Function That Never Yields Anything"