Skip to content

Object Model

CPython treats almost every value as an object, so attribute lookup, method calls, mutability, identity, `__slots__`, and many performance tradeoffs all connect back to the object model.

Quick takeaway: a CPython object is useful to picture as "reference count + pointer to type + value fields." Type objects and slots drive attribute access, operator behavior, and method binding.

Start With the Structure

Objects point to their types, and type objects hold behavior rules and slots. Syntax and attribute access are resolved through that structure.

What a Bound Method Carries

py
class User:
    def greet(self) -> str:
        return "hello"


user = User()
method = user.greet

print("bound method type:", type(method).__name__)
print("method.__self__ is user:", method.__self__ is user)
print("method.__func__ is User.greet:", method.__func__ is User.greet)

When you access a function through an instance, CPython creates a bound method object that carries both the original function and the bound instance.

When __slots__ Helps

py
class RegularUser:
    def __init__(self, name: str, age: int) -> None:
        self.name = name
        self.age = age


class SlottedUser:
    __slots__ = ("name", "age")

    def __init__(self, name: str, age: int) -> None:
        self.name = name
        self.age = age
  • __slots__ can reduce per-instance memory by removing the instance dictionary.
  • It also changes flexibility and some introspection behavior.
  • That makes it a targeted optimization tool, not a default style.

Why Mutability and Identity Matter Together

  • immutable objects make sharing easier
  • mutable objects separate identity from changing value
  • cache keys, shared state, and default-argument surprises all connect here

Practical Connections

  • attribute-heavy domain models
  • when to consider __slots__
  • intuition for method dispatch cost

Checklist

Attribute access has a cost model

Readable syntax still goes through descriptors, instance dictionaries, and class lookup.

Bound methods are objects too

Repeated method access has a small but real object-model cost.

Use `__slots__` intentionally

It is a memory and layout optimization, not a universal best practice.

Keep identity separate from value

That distinction becomes important whenever mutable state is shared or cached.

Official Sources

Built with VitePress for a Python 3.14 handbook.