How does polymorphism and duck typing work in Python?

· Category: Python Programming

Short answer

Python uses duck typing: if an object implements the needed methods, it can be used regardless of its class. This form of polymorphism prioritizes behavior over type, making code flexible and easy to extend.

Steps

  1. Write functions that expect certain methods or attributes rather than specific types.
  2. Use hasattr() and callable() for defensive checks when necessary.
  3. Prefer EAFP (Easier to Ask Forgiveness than Permission) with try/except.
class Dog:
    def speak(self):
        return "Woof"

class Cat:
    def speak(self):
        return "Meow"

def animal_sound(animal):
    return animal.speak()

print(animal_sound(Dog()))
print(animal_sound(Cat()))

# EAFP
class Duck:
    def quack(self):
        return "Quack"

def make_noise(obj):
    try:
        return obj.quack()
    except AttributeError:
        return "Silence"

print(make_noise(Duck()))
print(make_noise(Dog()))

Tips

  • Abstract base classes from collections.abc formalize duck typing with register() and subclass hooks.
  • typing.Protocol (Python 3.8+) enables static checking of duck-typed interfaces.
  • Avoid excessive isinstance() checks; they reduce the flexibility that duck typing provides.

Common issues

  • Duck typing can lead to subtle bugs when objects have methods with the same name but different semantics.
  • Missing methods raise AttributeError at runtime rather than being caught during type checking.
  • Over-reliance on duck typing in large codebases can make interfaces implicit and harder to document.