In the realm of Python, an object is the fundamental building block for data. Think of an object as a concrete entity that exists in your computer's memory. Whenever you create a piece of data, like the number 42, the string "hello", or a list [1, 2, 3], Python internally creates an object to represent that data. This "everything is an object" philosophy is central to Python's design, extending to functions, classes, and modules as well.
Objects are instances of classes (which can be built-in, like int or str, or user-defined). A class acts as a blueprint, defining the structure and behavior of its objects.
Every object in Python possesses three key attributes:
id() function. For example, id(42) will give you the unique ID of the integer object representing 42. This ID remains constant for the lifetime of the object.int can be used in arithmetic operations, while an object of type str has methods for text manipulation. The type can be found using the type() function (e.g., type("hello") returns <class 'str'>). An object's type is fixed once it's created.42, "hello"). For more complex objects like lists or custom class instances, the value might be a collection of other objects or a set of attributes. Some objects are mutable (their value can change after creation, like lists), while others are immutable (their value cannot change, like integers and strings).A variable in Python is not a box that holds data. Instead, it's a name or a label that you, the programmer, assign to an object. When you write an assignment statement like message = "Hello, Python!", you are not putting the string "Hello, Python!" *inside* the variable message. Rather, you are doing two things:
message is then bound to (or made to refer to) this string object.Think of variables as sticky notes that you can attach to different objects. The variable itself doesn't contain the object's data; it simply points to where the object is located in memory.
my_data can point to an integer object at one moment (my_data = 10) and a string object later (my_data = "text"). Python is dynamically typed, meaning type checking happens at runtime.To crystallize the differences, consider the following table which summarizes the core distinctions between variables and objects in Python:
| Feature | Variable | Object |
|---|---|---|
| Nature | A name, label, or symbolic reference. | The actual data entity residing in memory. |
| Stores | A memory address (reference) of an object. | The actual value or data content. |
| Type | Does not have an intrinsic type; derives it from the referenced object. | Has a specific, fixed type (e.g., int, str, list, custom class). |
| Identity | Does not have its own unique ID; uses the ID of the object it points to. | Has a unique identity (memory address), accessible via id(). |
| Creation | Created (or bound) through an assignment statement (e.g., name = value). |
Created when a value is defined, an expression is evaluated, or a class instance is instantiated. |
| Mutability Aspect | Can be reassigned to point to different objects (even of different types). | Its value can be mutable (e.g., lists, dictionaries) or immutable (e.g., integers, strings, tuples). Mutability is a property of the object. |
| Analogy | A label on a box, a pointer, a name tag. | The content inside the box, the "thing" itself. |
| Existence | Exists within a specific scope (namespace) and for a defined lifetime. | Exists in memory as long as it's referenced by at least one variable or data structure (otherwise, it may be garbage collected). |
Understanding the relationship between variables and objects is key. The following mindmap illustrates this conceptual model, showing how variables act as intermediaries to access the actual data stored in objects.
A common and helpful analogy is to think of "variable land" and "object land." Variables reside in "variable land" (conceptually, a namespace) and are like signposts. Each signpost (variable) has a name and points to a specific location in "object land" (memory), where the actual object resides. When your Python code uses a variable, Python follows the "pointer" from the variable to the object to perform operations or retrieve its value.
Visual representation of a Python variable (my_var) acting as a reference or pointer to an object stored in memory.
The radar chart below offers a visual comparison of variables and objects across several key characteristics. This helps to quickly grasp their distinct roles and properties within Python's ecosystem. An "Object" is the actual data entity, while a "Variable" is a name that refers to it.
This chart visually emphasizes that objects are the entities that directly hold data, possess intrinsic types, and unique identities. Variables, conversely, excel in their ability to be reassigned and primarily function as names within namespaces, referencing these objects.
Objects are where the data physically resides. The type of an object (e.g., int, str, list) dictates how that data is interpreted and what operations are valid. A variable, on the other hand, doesn't store data or have a type itself; it merely "borrows" the type of the object it currently points to for type-checking purposes.
Every object has a unique id(), which is constant throughout its existence. Objects live in memory as long as they are reachable (i.e., at least one variable or data structure refers to them). When an object is no longer referenced, Python's garbage collector may reclaim its memory. Variables exist within a certain scope (e.g., global, local to a function) and are destroyed when they go out of scope, which might lead to an object being garbage collected if that was its last reference.
Mutability is a characteristic of objects. Mutable objects (like lists or dictionaries) can have their content changed after creation. Immutable objects (like integers, strings, or tuples) cannot. For example, if my_list = [1, 2], then my_list.append(3) changes the object my_list refers to, so it becomes [1, 2, 3].
Variables, however, can always be reassigned. If you have x = 10 (x points to the integer object 10), and then you execute x = "hello", the variable x now points to a completely new string object "hello". The original integer object 10 is unaffected (and might be garbage collected if x was its only reference).
Understanding this distinction is crucial for writing correct and efficient Python code, especially when dealing with mutable data structures and function calls.
# Python code
x = 100
# Interpretation:
# 1. An integer object with the value 100 is created in memory.
# 2. The variable 'x' is created (if it doesn't exist in the current scope)
# and is made to reference/point to this integer object 100.
print(type(x)) # Output: <class 'int'> (the type of the object x points to)
print(id(x)) # Output: A unique ID of the integer object 100
When you assign one variable to another, both variables end up pointing to the exact same object.
# Python code
original_list = [1, 2, 3]
alias_list = original_list # 'alias_list' now points to the SAME list object as 'original_list'
print(f"Original list ID: {id(original_list)}")
print(f"Alias list ID: {id(alias_list)}") # Will be the same ID
# Modifying the object via one variable affects the other
alias_list.append(4)
print(f"Original list after modification: {original_list}") # Output: [1, 2, 3, 4]
print(f"Alias list after modification: {alias_list}") # Output: [1, 2, 3, 4]
Illustration of two variables, list1 and list2 (analogous to original_list and alias_list), referencing the identical list object in memory. Changes via one are visible via the other.
Reassigning a variable makes it point to a new object, leaving the original object (and any other variables pointing to it) untouched.
# Python code
a = 50 # 'a' points to the integer object 50
b = a # 'b' also points to the integer object 50
print(f"ID of object 'a' points to: {id(a)}")
print(f"ID of object 'b' points to: {id(b)}") # Same as id(a)
# Reassign 'a' to a new object
a = 75 # 'a' now points to a NEW integer object 75.
# The original integer object 50 still exists, and 'b' still points to it.
print(f"After reassigning 'a':")
print(f"Value of 'a': {a}") # Output: 75
print(f"Value of 'b': {b}") # Output: 50 (still points to the original object)
print(f"ID of object 'a' now points to: {id(a)}") # Different from original id(a)
print(f"ID of object 'b' still points to: {id(b)}") # Same as original id(b)
This diagram shows a variable x first pointing to an object with value 10, and then being reassigned to point to a new object with value 20, demonstrating variable reassignment.
The behavior becomes particularly important with mutable objects passed to functions.
# Python code
def modify_list_and_string(my_list, my_string):
my_list.append(100) # Modifies the original list object (lists are mutable)
my_string = my_string + " world" # Creates a NEW string object and rebinds 'my_string' locally
print(f"Inside function: List is {my_list}, String is {my_string}")
return my_string # return new string
# Immutable example (string)
immutable_val = "hello"
print(f"Before function (string): {immutable_val}, ID: {id(immutable_val)}")
new_string_val = modify_list_and_string([], immutable_val) # Pass empty list for this example
print(f"After function (string): {immutable_val}, ID: {id(immutable_val)}") # Unchanged
print(f"Returned string from function: {new_string_val}, ID: {id(new_string_val)}") # New object
# Mutable example (list)
mutable_val = [10, 20]
print(f"Before function (list): {mutable_val}, ID: {id(mutable_val)}")
modify_list_and_string(mutable_val, "") # Pass empty string for this example
print(f"After function (list): {mutable_val}, ID: {id(mutable_val)}") # Changed
In the case of my_list (mutable), modifications inside the function affect the original object because the function receives a reference to that same object. For my_string (immutable), the operation my_string + " world" creates a new string object, and the local variable my_string within the function is rebound to this new object. The original string object outside the function remains unchanged.
To further solidify your understanding, the following video offers an alternative model and explanation of Python variables and objects, emphasizing the object-oriented nature of the language. It visually breaks down how variables act as references to objects in memory, which can be very helpful for grasping these abstract concepts.
This video discusses how Python's variable model differs from some other languages, illustrating that variables are more like labels pointing to objects rather than containers holding values. This perspective is crucial for understanding Python's memory management, how data is passed to functions (pass-by-object-reference), and the implications of mutability.
id() function in Python?
To deepen your understanding of Python's data model, consider exploring these related topics: