I am trying to partition some code that scans input in a nontrivial way, from the code that consumes pieces of that input, but also want to support generation/iteration, and I wonder what is the most pythonic way to do this.
The easy way to get what I want is not to support iteration, and split responsibility into a Scanner and a ScanHandler:
import abc
class ScanHandler(abc.ABC):
@abc.abstractmethod
def onFoo(foo):
""" handle a foo """
pass
@abc.abstractmethod
def onBar(bar):
""" handle a bar """
pass
@abc.abstractmethod
def onBaz(baz):
""" handle a baz """
pass
class Scanner:
...
def scan(someInput, handler : ScanHandler):
for chunk in someInput:
... complicated logic ...
if ... something ...:
foo = ...
handler.onFoo(foo)
if ... something else ...:
bar = ...
handler.onBar(bar)
if ... something else ...:
baz = ...
handler.onBaz(baz)
Then the handler object can do whatever it wants with the foo/bar/baz bits that are scanned.
But in some cases all I want to do is handle foo pieces, and I'd like to just do something like:
for foo in scanner.someMethod(someInput):
... handle each foo ...
and I can't figure out how to do this unless I change the Scanner architecture to
class Scanner:
...
def scan(someInput):
for chunk in someInput:
... complicated logic ...
if ... something ...:
foo = ...
yield foo
if ... something else ...:
bar = ...
yield bar
if ... something else ...:
baz = ...
yield baz
and then if I want to just handle the foo objects, I have to do something like:
def filterOnlyFoo(things):
for thing in things:
if [thing is a foo]: # annoying extra work
yield thing
for foo in filterOnlyFoo(scanner.scan(someInput)):
doSomethingWithFoo
Is there a more straightforward design that would make sense to use here?
filter()function? You don't even need to import it.Fooobjects and check withisinstance(object, Foo)or, if you prefer you can do something like create an Enum of foo, bar, baz and set a field on the emitted objects with the appropriate one.ifstatement (or even the need to definefilterOnlyFoo); or do you refer to the work happening in the complicated logic ofif ... something ...: bar = ...that you would like to optimise away when you know beforehand that you will only handlefoos?