Fundamentals 8 min read

Why Overusing isinstance() Makes Python Code Rigid – Better Practices

This article explains why relying heavily on Python's isinstance() for type checking leads to less flexible code, introduces the EAFP vs. LBYL philosophies, and shows when isinstance() is appropriate through clear examples and best‑practice guidelines.

Code Mala Tang
Code Mala Tang
Code Mala Tang
Why Overusing isinstance() Makes Python Code Rigid – Better Practices

I used to heavily rely on isinstance() in my code, believing that explicit type checks were good practice. I was wrong. Below is why I stopped abusing isinstance() and how it makes my code cleaner and more flexible.

Fundamentals

isinstance() is a built‑in Python function that checks whether an object is an instance of a specific class or type.

<code>print(isinstance(123, int))  # True</code>

It seems simple, so I started using it everywhere, for example:

<code>def double(value):
    if isinstance(value, int):
        return value * 2
    else:
        return None</code>

That code runs, but it isn’t idiomatic Python. Here’s why.

Problem #1: This Violates Pythonic Style

Python is dynamic; we usually care about what an object can do, not its exact type. This is the "duck typing" principle: if it walks like a duck and quacks like a duck, treat it as a duck.

“If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.”

Therefore we can write more generic code:

<code>def double(value):
    return value * 2</code>

This works for int , float , and even str (e.g., "hello" * 2 yields "hellohello" ).

Problem #2: You Restrict Yourself

I once wrote a function that only accepted list arguments:

<code>def total(items):
    if not isinstance(items, list):
        raise TypeError("items must be a list")
    return sum(items)</code>

When I passed a tuple , the function failed even though sum((1, 2, 3)) works fine. A better version simply relies on the operation itself:

<code>def total(items):
    return sum(items)</code>

We should test behavior, not type.

Use EAFP Instead of LBYL

Pythonic code prefers EAFP (Easier to Ask Forgiveness than Permission) over LBYL (Look Before You Leap).

EAFP : try the operation and handle exceptions.

LBYL : check the type before acting.

LBYL example (not recommended):

<code>if isinstance(obj, list):
    obj.append(5)</code>

EAFP example (preferred):

<code>try:
    obj.append(5)
except AttributeError:
    print("Object does not support append")</code>

EAFP works even when obj is a custom object that implements append , something a strict isinstance() check would miss.

If You Have Multiple Types, Don’t Use isinstance()

Instead of checking for several concrete types, attempt the operation and catch relevant exceptions:

<code>def inverse(x):
    try:
        return 1 / x
    except ZeroDivisionError:
        return float('inf')
    except TypeError:
        return None</code>

When isinstance() Is Acceptable

There are cases where explicit type checks are reasonable.

1. Checking Abstract Base Classes (ABCs)

When we care about an "iterable" behavior rather than a concrete type like list or tuple , using isinstance() with an ABC is fine.

2. Deserialization / JSON handling

<code>def parse_age(data):
    if isinstance(data, dict) and 'age' in data:
        return int(data['age'])
    return None</code>

Here we need to ensure the incoming structure is a dictionary before accessing keys.

3. When Polymorphism Is Not Feasible

If two classes don’t share a common interface, a temporary isinstance() check can be used:

<code>class Cat:
    def meow(self):
        print("meow")

class Dog:
    def bark(self):
        print("woof")

def talk(animal):
    if isinstance(animal, Cat):
        animal.meow()</code>

A better design would give both classes a shared method like speak() , but the check is acceptable when redesign isn’t possible.

Advanced Technique

For ultimate control, you can create a custom metaclass that overrides __instancecheck__ to change how isinstance() behaves.

custom metaclass __instancecheck__
custom metaclass __instancecheck__

This technique enables highly flexible systems when such fine‑grained control is required.

Summary

Avoid writing code like:

<code>if isinstance(x, list):
    do_something()</code>

Instead, prefer:

<code>try:
    x.append(5)
except AttributeError:
    handle_it()</code>

Let Python naturally handle incorrect inputs, and write functions that focus on behavior rather than explicit type checks.

PythonBest Practicestype checkingduck typingisinstancemetaclassEAFP
Code Mala Tang
Written by

Code Mala Tang

Read source code together, write articles together, and enjoy spicy hot pot together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.