0

I would like to write a class with the following interface.

class Automaton:
    """ A simple automaton class """
    def iterate(self, something):
        """ yield something and expects some result in return """
        print("Yielding", something)
        result = yield something
        print("Got \"" + result + "\" in return")
        return result

    def start(self, somefunction):
        """ start the iteration process """
        yield from somefunction(self.iterate)
        raise StopIteration("I'm done!")


def first(iterate):
    while iterate("what do I do?") != "over":
        continue


def second(iterate):
    value = yield from iterate("what do I do?")
    while value != "over":
        value = yield from iterate("what do I do?")


# A simple driving process
automaton = Automaton()
#generator = automaton.start(first)    # This one hangs
generator = automaton.start(second)    # This one runs smoothly
next_yield = generator.__next__()
for step in range(4):
    next_yield = generator.send("Continue...({})".format(step))
try:
    end = generator.send("over")
except StopIteration as excp:
    print(excp)


The idea is that Automaton will regularly yield values to the caller which will in turn send results/commands back to the Automaton.

The catch is that the decision process "somefunction" will be some user defined function I have no control over. Which means that I can't really expect it to call the iterate method will a yield from in front. Worst, it could be that the user wants to plug some third-party function he has no control over inside this Automaton class. Meaning that the user might not be able to rewrite his somefunction for it to include yield from in front of iterate calls.

To be clear: I completely understand why using the first function hangs the automaton. I am just wondering if there is a way to alter the definition of iterate or start that would make the first function work.

  • What would it look like to make the `first` function "work"? It is not a generator, and `yield from` will always fail. If your `start` function requires the argument to be a generator, you can add a check for that and raise a `TypeError` if the caller gives normal function like `first` – Hymns For Disco Feb 21 '20 at 11:16
  • I think you many find [How do I form multiple pipelines with generators?](https://stackoverflow.com/questions/45924087/how-do-i-form-multiple-pipelines-with-generators) helpful. – martineau Feb 21 '20 at 11:36

0 Answers0