← Back to Python

Duck Typing

PythonEntrypython

The Question

What is duck typing in Python?

What a Strong Answer Covers

  • behavior over type
  • "no inheritance needed

Senior-Level Answer

Duck typing is a programming style where an object's suitability for a use is determined by the presence of the required methods and attributes, not by its class hierarchy. The name comes from the phrase: "If it walks like a duck and quacks like a duck, then it must be a duck."

In statically typed languages like Java, you must declare that a class implements an interface before you can pass it to a function expecting that interface. In Python, no such declaration is needed — if the object has the method the function calls, it works. If it doesn't, a `AttributeError` is raised at the point of the call.

A concrete example: Python's `len()` function works on any object that implements `__len__`. It does not require the object to inherit from a `Sequence` base class. A custom class with `__len__` defined is fully compatible. Similarly, any object implementing `__iter__` and `__next__` can be used in a `for` loop — no base class required.

Duck typing enables highly flexible and composable code. The `sorted()` built-in works on any iterable; `json.dump()` accepts any file-like object with a `write()` method; context managers work for any object implementing `__enter__` and `__exit__`. This is why Python's standard library APIs are so interoperable with user-defined types without requiring inheritance.

The trade-off is that type errors are deferred to runtime. A wrong argument type passes undetected until the missing method is called — potentially deep in a call stack with a confusing error message. **Type hints** (PEP 484, Python 3.5+) and static analysis tools like `mypy` and `pyright` address this by adding optional static type checking without changing runtime behavior. **Protocols** (PEP 544, Python 3.8+) formalize duck typing: a `Protocol` class defines the required interface structurally, and `mypy` checks conformance without requiring inheritance — this is called **structural subtyping**.

Duck typing is distinct from inheritance-based polymorphism. With inheritance, you declare the relationship upfront. With duck typing (and Protocols), the relationship is implicit and checked by behavior.

What Separates a 2/3 from a 3/3

2/3 — Passing but Incomplete

Correctly explains the concept with a code example and names the runtime-error trade-off. May not distinguish duck typing from structural subtyping via Protocols.

3/3 — Strong Answer

Gives a precise definition, provides a concrete Python example using dunder methods, explains how type hints and Protocols formalize duck typing for static analysis, and contrasts it with nominal typing used in statically typed languages.

Common Mistakes

  • Describing duck typing as 'Python has no types' — Python has strong dynamic types; duck typing is about structural compatibility, not the absence of types.
  • Not mentioning that duck typing errors surface at runtime, not definition time.
  • Being unaware of Protocols as the modern formalization of duck typing for static analysis.
  • Confusing duck typing with dynamic typing — they are related but distinct concepts.

Follow-Up Questions

  • What is a Python Protocol and how does it differ from an ABC (Abstract Base Class)? — Protocol uses structural subtyping — a class satisfies the protocol if it has the required methods, without explicit inheritance. ABCs require explicit inheritance and can enforce method implementations at class definition time.
  • How would you use isinstance() checks to add some type safety while preserving duck typing flexibility? — ABCs like collections.abc.Iterable support isinstance() checks via __subclasshook__, so isinstance(x, Iterable) returns True for any object with __iter__ without needing explicit inheritance.
  • What is EAFP (Easier to Ask Forgiveness than Permission) and how does it relate to duck typing? — EAFP: try the operation and catch exceptions rather than pre-checking types/attributes. Contrasts with LBYL (Look Before You Leap). Duck typing naturally leads to EAFP-style code.
  • How would you design a function that accepts either a file path string or a file-like object? — Check for the write/read method (duck typing) rather than isinstance(arg, str). Or use Union[str, IO[str]] type hint with a Protocol for the file-like contract.

Related Questions

  • GIL — What It Is and What It Protects
  • ThreadPoolExecutor & ProcessPoolExecutor
  • Decorators — Under the Hood
  • Generators & yield
  • Context Managers

Can You Explain This Cold?

Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.

Get Graded — Free Assessment
GrindQuestionsAITechnical interview assessment
TermsPrivacyAbout