← Home

014. Type() Function

Inspect runtime types for defensive programming

014. Type() Function

Aryan’s RAM monitor exposes a function set_threshold(value) that users call to change the memory warning threshold. The value must be an integer — a float or string would cause downstream math errors.

He writes a validator but makes a subtle mistake: it uses isinstance() which accepts subclasses. True is a subclass of int, so isinstance(True, int) returns True. That means someone can call set_threshold(True) and it passes — setting the threshold to 1 MB (True == 1) and immediately triggering non-stop warnings.

The fix: use type(value) == int for exact type matching. type(True) == int is False because True is a bool, not an int.

Apply the same lesson to the API validator below.


💡 Fun fact: type() is one of Python’s oldest built-in functions and has a dual personality: with one argument it inspects a type, with three arguments it creates a new class dynamically at runtime. This metaclass usage is how Python’s ORM frameworks like Django create model classes from simple attribute definitions.

⚠️ Watch out: isinstance(True, int) returns True because bool is a subclass of int — so isinstance is too permissive for strict API validation. Use type(value) == int when you need to reject booleans, since type(True) == int is False.

Learning objectives

  • Use type() to inspect the exact type of a value
  • Understand the difference between type() and isinstance()
  • Know that bool is a subclass of int

Key concepts

  • type()
  • runtime type inspection
  • type comparison

Try it

Concept detail

type(x) returns the exact class object of x. It does NOT consider inheritance.

Comparison: type(True) == int → False (True is bool, not int) isinstance(True, int) → True (bool IS-A int via subclassing)

type(42) == int → True type(42) == float → False (42 is int, not float, even though 42 == 42.0)

Use type() == when you need exact type matching — e.g., in API validators, serializers, or protocol implementations where bool should not silently substitute for int.

Use isinstance() when subclass relationships are intentional — e.g., accepting any numeric type, or accepting any sequence type (list, tuple, etc.).

The broken_code bug: isinstance(True, int) returns True, so validate_params(True, 9.99, “order”) passes. In the RAM monitor context, a threshold of True (== 1 MB) would fire constant alerts. The fix (type() ==) rejects booleans because their exact type is bool, not int.

Additional type() facts: type(42).name → ‘int’ (get type name as string) type(x) with 3 args → creates a new class (advanced metaclass usage) print(type(x)) → <class ‘int’>

Solution

def validate_params(user_id, amount, label):
    return (
        type(user_id) == int
        and type(amount) == float
        and type(label) == str
    )

Tests

def test_all_correct_types():
    assert validate_params(42, 9.99, "order") == True

def test_user_id_wrong_type():
    assert validate_params("42", 9.99, "order") == False

def test_amount_wrong_type():
    assert validate_params(42, 10, "order") == False

def test_label_wrong_type():
    assert validate_params(42, 9.99, 123) == False

def test_none_fails():
    assert validate_params(None, 9.99, "order") == False

def test_bool_rejected_as_user_id():
    assert validate_params(True, 9.99, "order") == False

Resources