I have some functions that have implementation details that depend on which type of object is passed to them (specifically, it's to pick the proper method to link Django models to generate QuerySets). Which of the two following options is the more Pythonic way to implement things?
If ladders
def do_something(thing: SuperClass) -> "QuerySet[SomethingElse]":
if isinstance(thing, SubClassA):
return thing.property_set.all()
if isinstance(thing, SubClassB):
return thing.method()
if isinstance(thing, SubClassC):
return a_function(thing)
if isinstance(thing, SubClassD):
return SomethingElse.objects.filter(some_property__in=thing.another_property_set.all())
return SomethingElse.objects.none()
Dictionary
def do_something(thing: SuperClass) -> "QuerySet[SomethingElse]":
return {
SubClassA: thing.property_set.all(),
SubClassB: thing.method(),
SubClassC: a_function(thing),
SubClassD: SomethingElse.objects.filter(some_property__in=thing.another_property_set.all()),
}.get(type(thing), SomethingElse.objects.none())
The dictionary option has less repeated code and fewer lines but the if ladders make PyCharm & MyPy happier (especially with type-checking).
I assume that any performance difference between the two would be negligible unless it's in an inner loop of a frequently-called routine (as in >>1 request/second).