Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

An object in Python is the fundamental abstraction for data. Every entity in a Python program—including numbers, strings, functions, classes, types, and modules—is an object. At the language implementation level, an object is a dynamically allocated block of memory containing structural metadata and data values. Every Python object is defined by three essential characteristics:
  1. Identity: A unique integer identifier assigned upon creation that remains constant throughout the object’s lifetime. The language specification guarantees this integer is unique among all simultaneously existing objects. While CPython implements this as the object’s memory address, other implementations (like PyPy or Jython) do not. Identity is evaluated using the id() function or the is operator.
  2. Type: A pointer to the object’s class. The type dictates the object’s memory layout, the operations it supports, and its behavior. It is evaluated using the type() function. In Python, types themselves are objects.
  3. Value: The actual data encapsulated by the object. If the value can be modified in place after creation, the object is classified as mutable (e.g., list, dict). If the value is fixed upon creation, the object is immutable (e.g., int, tuple, str).
x = [10, 20]


# Identity evaluation
print(id(x))          # e.g., 139824510485120
print(x is [10, 20])  # False (different identities)


# Type evaluation
print(type(x))        # <class 'list'>


# Value mutation
x.append(30)          # Modifies the value in place; identity remains unchanged

Attribute Storage and Resolution

Objects store state (data) and behavior (methods) as attributes. For most user-defined objects, Python stores instance attributes internally in a dynamic dictionary, accessible via the __dict__ attribute. When an attribute is accessed (e.g., instance.attribute), Python resolves the lookup using a strict hierarchy, rather than simply checking the instance dictionary first. The resolution order is:
  1. Data Descriptors: Attributes defined on the class that implement both __get__ and __set__ (such as @property). These take absolute precedence over the instance dictionary.
  2. Instance Dictionary: The instance’s own __dict__.
  3. Class Dictionary & Non-Data Descriptors: Attributes defined on the class, including standard methods (which implement only __get__).
When searching the class and its ancestors for descriptors or class attributes, Python traverses the inheritance hierarchy according to the Method Resolution Order (MRO). The MRO strictly governs the search order among a class and its base classes, not the lookup order between an instance and its class.
class Entity:
    def __init__(self):
        self.status = "active"
        
    @property
    def code(self):
        return 200

instance = Entity()
instance.__dict__['code'] = 404  # Manually injecting into the instance dictionary


# Inspecting the underlying attribute dictionary
print(instance.__dict__)  # {'status': 'active', 'code': 404}


# The data descriptor (@property) takes precedence over the instance dictionary
print(instance.code)      # 200

The Python Data Model (Dunder Methods)

An object’s interaction with Python’s syntax and built-in functions is governed by the Python Data Model. Objects implement special methods—often called “dunder” (double underscore) methods—to define their behavior for operations like initialization, arithmetic, iteration, and representation.
class Matrix:
    def __init__(self, value):
        self.value = value
        
    # Defines behavior for the '+' operator (obj1 + obj2)
    def __add__(self, other):
        return Matrix(self.value + other.value)
        
    # Defines the developer-facing string representation
    def __repr__(self):
        return f"Matrix({self.value})"

m1 = Matrix(5)
m2 = Matrix(10)


# Implicitly invokes m1.__add__(m2)
m3 = m1 + m2 

Object Lifecycle and Memory Management

Objects are dynamically allocated on the private heap. Python manages object lifecycles primarily through reference counting, supplemented by a cyclic garbage collector to detect reference cycles. Every object maintains an internal counter of variables or data structures referencing it. When an object’s reference count drops to zero, Python’s memory manager immediately reclaims the memory block.
import sys

target_obj = {"key": "value"}


# sys.getrefcount() returns the number of references to the object.

# Note: Passing the object to getrefcount() temporarily increases the count by 1.
print(sys.getrefcount(target_obj))  # 2


# Removing the reference
del target_obj 

# The dictionary object's reference count drops to 0 and is deallocated.
Master Python with Deep Grasping Methodology!Learn More