Hyppää sisältöön

Ei vielä käännetty

Tätä sivua ei ole vielä käännetty suomeksi, joten se näytetään englanniksi. Auta kääntämään

isinstance() Function Complexity

The isinstance() function checks whether an object is an instance of a class or a tuple of classes, following inheritance relationships.

Complexity Reference

Operation Time Space Notes
isinstance(obj, type) O(d) O(1) d = MRO depth; effectively O(1) for typical hierarchies
isinstance(obj, (type1, type2, ...)) O(k*d) O(1) k = number of types; short-circuits on first match
isinstance(obj, abstract_base) O(d) to O(n) O(1) Depends on ABC subclasshook implementation

Basic Type Checking

Simple Type Checks

# Single type - O(1)
x = 42
isinstance(x, int)           # True - O(1)
isinstance(x, str)           # False - O(1)
isinstance(x, (int, float))  # True - O(2)

# Works with built-in types
isinstance([1, 2], list)     # True - O(1)
isinstance({'a': 1}, dict)   # True - O(1)
isinstance((1, 2), tuple)    # True - O(1)

Tuple of Types

# Multiple types - O(k) where k = number of types
numeric_types = (int, float, complex)
isinstance(42, numeric_types)           # True - O(3)
isinstance(3.14, numeric_types)         # True - O(3)
isinstance("3.14", numeric_types)       # False - O(3)

# Checking against all sequence types - O(k)
sequence_types = (list, tuple, range, str, bytes)
isinstance([1, 2, 3], sequence_types)   # True - O(5)

Inheritance Checking

Class Hierarchies

# Define class hierarchy - O(1)
class Animal:
    pass

class Dog(Animal):
    pass

class Cat(Animal):
    pass

# Check inheritance - O(1)
dog = Dog()
isinstance(dog, Dog)      # True - O(1)
isinstance(dog, Animal)   # True - O(1) - follows inheritance
isinstance(dog, Cat)      # False - O(1)

# Check against base class
isinstance(dog, (Dog, Cat))  # True - O(2)

Deep Inheritance Chains

# Multi-level inheritance - O(1)
class A: pass
class B(A): pass
class C(B): pass
class D(C): pass

obj = D()
isinstance(obj, D)  # True - O(1)
isinstance(obj, A)  # True - O(1) - checks up the chain

# Multiple base classes (MRO) - O(1)
class X: pass
class Y: pass
class Z(X, Y): pass

z = Z()
isinstance(z, X)  # True - O(1)
isinstance(z, Y)  # True - O(1)

Common Patterns

Type-based Dispatching

# Dispatch based on type - O(k) for checking, O(1) for dispatch
def process(obj):
    if isinstance(obj, int):
        return obj * 2  # O(1)
    elif isinstance(obj, str):
        return obj.upper()  # O(n) for string
    elif isinstance(obj, list):
        return len(obj)  # O(1)
    else:
        return None  # O(1)

# Total complexity: O(k) checks + O(operation complexity)

Batch Type Checking

# Check multiple items against types - O(n*k)
items = [1, "hello", 3.14, None, [1, 2]]
numeric_types = (int, float)

# Count numeric items - O(n*k)
count = sum(1 for item in items if isinstance(item, numeric_types))
# 2 items are numeric - O(5 * 2) = O(10)

Filtering by Type

# Filter items by type - O(n*k)
items = [1, "a", 2, "b", 3, "c"]
strings = [item for item in items if isinstance(item, str)]
# O(6 * 1) = O(6)

numbers = [item for item in items if isinstance(item, (int, float))]
# O(6 * 2) = O(12)

Built-in Type Checking

All Built-in Types

# isinstance() works with all built-in types - O(1) each
isinstance(42, int)              # True
isinstance(3.14, float)          # True
isinstance("hello", str)         # True
isinstance([1, 2, 3], list)      # True
isinstance((1, 2), tuple)        # True
isinstance({1, 2, 3}, set)       # True
isinstance({'a': 1}, dict)       # True
isinstance(b'bytes', bytes)      # True
isinstance(True, bool)           # True
isinstance(True, int)            # True - bool is subclass of int!

# Check multiple built-in types
isinstance(42, (int, float))     # True - O(2)
isinstance("hello", (str, bytes))  # True - O(2)

Important Relationship: bool is int

# bool is a subclass of int - important!
isinstance(True, bool)           # True - O(1)
isinstance(True, int)            # True - O(1) - bool inherits from int
isinstance(1, bool)              # False - O(1) - int is not necessarily bool

# This matters in type checking
def check_bool_only(value):
    return isinstance(value, bool)  # O(1) - stricter check

def check_int_like(value):
    return isinstance(value, int)   # O(1) - includes bool!

Abstract Base Classes (ABCs)

Standard ABCs

from collections.abc import Sequence, Mapping, Iterable

# ABC checking - O(1) typically
numbers = [1, 2, 3]
isinstance(numbers, Sequence)  # True - O(1)

d = {'a': 1}
isinstance(d, Mapping)         # True - O(1)

# Works with iterables
gen = (x for x in range(10))
isinstance(gen, Iterable)      # True - O(1)

# Check strings
isinstance("hello", Sequence)  # True - O(1)
isinstance("hello", str)       # True - O(1)

Custom ABC Implementation

from abc import ABC, abstractmethod

# Define custom ABC - O(1)
class DataProcessor(ABC):
    @abstractmethod
    def process(self, data):
        pass

class ListProcessor(DataProcessor):
    def process(self, data):
        return [x * 2 for x in data]

# Check against ABC - O(1)
proc = ListProcessor()
isinstance(proc, DataProcessor)     # True
isinstance(proc, DataProcessor.__subclasses__())  # O(subclasses)

Performance Considerations

Tuple vs Multiple isinstance Calls

# Option 1: Single isinstance with tuple - O(k)
result = isinstance(obj, (int, float, complex, bool))  # O(4)

# Option 2: Multiple isinstance calls - O(k)
result = (isinstance(obj, int) or 
          isinstance(obj, float) or 
          isinstance(obj, complex) or
          isinstance(obj, bool))  # O(4) - short-circuits

# Same complexity but tuple is cleaner

Avoid Expensive Checks in Loops

# Bad: Check complex ABC in loop - O(n*k)
def is_valid_items(items):
    from collections.abc import Sequence
    for item in items:
        if not isinstance(item, Sequence):  # O(k) per item
            return False
    return True
# Total: O(n*k)

# Better: Check once, then iterate
def is_valid_items(items):
    if not isinstance(items, list):  # O(1)
        return False
    for item in items:
        # Process without checking
        process(item)  # O(1)
    return True
# Total: O(n)

isinstance vs type()

# isinstance checks inheritance - O(1)
class Animal: pass
class Dog(Animal): pass
dog = Dog()

isinstance(dog, Animal)  # True - checks inheritance
type(dog) is Animal      # False - exact type only
type(dog) is Dog         # True

# isinstance is preferred for flexibility
# type() is O(1) and exact, but less flexible

Special Cases

None Type

# Check for None - O(1)
value = None
isinstance(value, type(None))  # True
isinstance(value, object)      # True - everything inherits from object

# Or use direct comparison
value is None  # True - preferred way for None

Union Type Hints

# Type hints don't affect isinstance behavior
def process(value: int | str):
    if isinstance(value, int):  # O(1)
        return value * 2
    elif isinstance(value, str):  # O(1)
        return value.upper()

# isinstance still O(1) per check

isinstance with Generic Types

from typing import List, Dict

# Generic types don't work directly with isinstance
lst = [1, 2, 3]
# isinstance(lst, List[int])  # TypeError

# Must use non-parameterized type
isinstance(lst, list)  # True - O(1)

# For runtime checking, use typing.get_args() - O(1)
import typing
if isinstance(lst, list):  # O(1)
    element_type = typing.get_args(List[int])  # O(1)

Version Notes

  • Python 2.x: Works with old-style and new-style classes
  • Python 3.x: All classes are new-style, consistent behavior
  • Python 3.10+: isinstance() can accept | union syntax in type hints (no change to isinstance performance)
  • issubclass() - Check class inheritance (O(1))
  • type() - Get exact type (O(1))
  • callable() - Check if callable (O(1))

Best Practices

Do:

  • Use isinstance(obj, (type1, type2)) for multiple types
  • Use ABCs for flexible type checking
  • Use isinstance() for inheritance-aware type checking
  • Cache expensive type checks

Avoid:

  • type(obj) is SomeType for inheritance (doesn't follow inheritance)
  • Expensive ABC checks in tight loops
  • Checking against too many types at once (long tuples)
  • Assuming isinstance() works with parameterized generics like List[int]