Learn a pattern to isolate packages while extending the functionalities of your Python code.

Dynamic polymorphism is the most powerful feature of object oriented programming, which allows us to program against abstractions whose real behavior is only defined at run time. It is also the only feature really defining OOP according to Robert C. Martin (of Clean Code fame).

Polymorphism consists of two parts: a method with type-dependent implementations and a method call that is type agnostic. In python code:

class TypeA:
def speak(self):
print("Hello, this is an object of type TypeA")
class TypeB:
def speak(self):
print("Greetings from type TypeB")
def agnostic_speak(speaker):
speaker.speak()
agnostic_speak(TypeA())
agnostic_speak(TypeB())
>> Hello, this is an object of type TypeA
Greetings from type TypeB

This trivial example shows the polymorphic method speak() and the generic function that calls it without knowing the actual type of the object on which the method is called.

For such a simple example, a conditional statement (if/else) based on the argument type would do the trick, but it comes with disadvantages. First, the conditional code makes the function more difficult to read. In this version we see immediately what it does, it makes an object speak, while with conditional code we would need to first understand what the different branches do. Also, if in the future we want to add more ways to speak, we would need to get back to this function and modify it to add new branches. In turn, the new branches will make the code less and less readable.

Let’s suppose we have a text classification app, which receives a line of text in input and outputs a label that represents its topic. Like any good machine learning project, we perform many iterations over different models and we want our code to use them all. For sure, we don’t want a big switch statement (if-elif-elif-…-else) with the logic to run any single model!

For the example’s sake, all models share the same input/output vocabularies, that is, the same mappings word->input index and output index->label. The only difference resides on the operations performed by the underlying model.

In the first version of our code we have only two model architectures: a feed-forward and an LSTM network, which provide the polymorphic forward() method encapsulating the logic for each model:

# main.py
from models import FfModel, LstmModel
def main(args):
model_type = args.model_type
model_path =...

Continue reading: https://towardsdatascience.com/python-polymorphism-with-class-discovery-28908ac6456f?source=rss—-7f60cf5620c9—4

Source: towardsdatascience.com