Python Essentials for AI Engineer

Course Content

Python Essentials for AI Engineer

6 sections · 48 lessons

What is Polymorphism?


One call, three unrelated classesclf.classify(text)KeywordBaseline — 2 of 3LLMClassifier — 3 of 3FakeClassifierin CI — 1 of 3Next quarter'sfine-tuned model
The harness never checks a class: any object with a classify method fits, with no shared parent needed.

What you need to know

Built-in polymorphism

You already use it daily. The same syntax does different things depending on the type:

Python
print(len("upi"), len([1, 2]), len({"a": 1}))    # 3 2 1print(1 + 2, "ab" + "cd", [1] + [2])             # 3 abcd [1, 2]

len calls each object's __len__; + calls each object's __add__.

Duck typing

Functions like json.load(f) accept any object with a .read() method — a real file, an io.StringIO, or a network stream. No shared parent class is involved.

Overriding

A subclass can replace a parent method (see the inheritance question). Code that calls model.predict(x) runs whichever version belongs to the object's actual class.

Checking duck types statically: Protocol

Duck typing is flexible but gives no warning when an object lacks a method. typing.Protocol describes the required methods so mypy or pyright can check them, still without inheritance:

Python
from typing import Protocolclass Classifier(Protocol):    def classify(self, text: str) -> str: ...

Any class with a matching classify method satisfies Classifier for the type checker.

No overloading by signature

Python has no Java-style method overloading. If you define def f(self, x) and then def f(self, x, y), the second replaces the first. Use default arguments, or functools.singledispatch to choose an implementation by argument type.

A real-life example

An evaluation harness compares three ticket classifiers on the same test set: a keyword baseline, an LLM, and a fake used in CI. The harness only calls .classify():

Python
class KeywordBaseline:    def classify(self, text):        return "refund" if "refund" in text.lower() else "other"class LLMClassifier:    def __init__(self, model):        self.model = model    def classify(self, text):        return "refund" if "money back" in text.lower() or "refund" in text.lower() else "other"  # stands in for an API callclass FakeClassifier:    def classify(self, text):        return "other"tests = [("I want my money back", "refund"), ("Refund pending", "refund"), ("Update address", "other")]for clf in [KeywordBaseline(), LLMClassifier("chat-small"), FakeClassifier()]:    score = sum(clf.classify(t) == y for t, y in tests)    print(f"{type(clf).__name__:<16} {score}/{len(tests)}")# KeywordBaseline  2/3# LLMClassifier    3/3# FakeClassifier   1/3

The three classes share no parent. Adding a fine-tuned model next quarter means writing one more class with a classify method; the harness, the reports and the CI job do not change.

Follow-up questions to expect

  • "Does Python support method overloading?" — Not by signature. A later definition replaces an earlier one; use defaults or functools.singledispatch.
  • "What is duck typing?" — Using an object based on the methods it has, not its class.
  • "How is polymorphism different from inheritance?" — Inheritance is one way to get polymorphism. In Python, duck typing gives polymorphism without any inheritance.