Unit 4 · Modules and File Handling
Introduction to Objects
Understand what objects are in Python, how everything revolves around objects, and learn to inspect identity, type, and mutability of data.
Introduction
In Python, everything is an object. Numbers, strings, lists, functions, and even modules are objects. Understanding objects is the foundation of mastering Python because it determines how data is stored, referenced, and manipulated in memory.
This chapter introduces you to the concept of objects, their identity, type, and whether they are mutable or immutable. These concepts are essential for writing efficient and bug-free programs, and they frequently appear in university exams and competitive programming interviews.
University Definition
An object in Python is a piece of data that has a type (class), a unique identity (memory address), and a value. Every variable in Python is actually a reference (name) that points to an object stored in memory. Objects can be mutable (value can change after creation) or immutable (value cannot change after creation).
Table of Contents
Everything is an Object in Python
Unlike many other programming languages, Python treats everything as an object — including primitive types like integers and floats, complex types like lists and dictionaries, functions, classes, and even modules.
An object consists of three core attributes:
- Identity — A unique integer (memory address) assigned to the object, obtained using
id(). - Type — The kind of object it is (e.g.,
int,str,list), obtained usingtype(). - Value — The actual data stored in the object.
# Every element is an object x = 10 print(type(x)) # <class 'int'> print(id(x)) # Unique memory address (integer) name = "Python" print(type(name)) # <class 'str'> print(id(name)) # Unique memory address my_list = [1, 2, 3] print(type(my_list)) # <class 'list'> print(id(my_list)) # Unique memory address
Real-life Analogy: Think of objects as items in a warehouse. Each item has a unique barcode (identity), a category label (type), and contents (value).
id() and type() Functions
Python provides two built-in functions to inspect objects:
University Definition
id() returns the unique identity of an object (its memory address as an integer). type() returns the type/class of the object. Both are built-in functions available without any import.
# Using id() and type() x = 42 print(id(x)) # e.g., 140234866547568 print(type(x)) # <class 'int'> y = "Hello" print(id(y)) # e.g., 140234866309456 print(type(y)) # <class 'str'> # Comparing objects a = 256 b = 256 print(a is b) # True (Python caches small integers) print(id(a) == id(b)) # True a = 257 b = 257 print(a is b) # May be False (outside cached range) print(a == b) # True (same value)
University Exam Tip
is checks identity (same object in memory), while == checks equality (same value). For small integers (-5 to 256), Python caches them, so is may return True even for separately created variables. Always use == to compare values.
Mutable vs Immutable Objects
Objects in Python are classified into two categories based on whether their value can be changed after creation.
University Definition
A mutable object is one whose state (value) can be modified after it is created without changing its identity. An immutable object is one whose state cannot be modified after creation; any apparent modification actually creates a new object.
Immutable Types
int,float,complex— Numbersstr— Stringstuple— Tuplesfrozenset— Frozen Setsbytes— Byte sequences
Mutable Types
list— Listsdict— Dictionariesset— Setsbytearray— Mutable byte arrays
# Immutable: string cannot be changed in place s = "Hello" print(id(s)) # e.g., 140234866309456 s = s + " World" # Creates a NEW string object print(id(s)) # Different address! e.g., 140234866309520 # Mutable: list CAN be changed in place lst = [1, 2, 3] print(id(lst)) # e.g., 140234866201280 lst.append(4) # Modifies the SAME list object print(id(lst)) # Same address! 140234866201280
University Exam Tip
When you pass an immutable object to a function, changes inside the function do NOT affect the original. When you pass a mutable object, changes inside the function DO affect the original. This is a common exam question.
Reference Variables and Aliasing
In Python, variables do not store values directly. Instead, they store references (pointers) to objects in memory. When you assign one variable to another, both reference the same object.
University Definition
Aliasing occurs when two or more variables reference the same object. Reference counting is Python's mechanism for garbage collection — when an object's reference count drops to zero, the memory is freed.
# Reference and Aliasing a = [10, 20, 30] b = a # b is an alias for a (same object) print(id(a) == id(b)) # True — same object b.append(40) print(a) # [10, 20, 30, 40] — a is also changed! # To create an independent copy, use slicing or copy() c = a[:] # Shallow copy d = a.copy() # Another way to shallow copy c.append(50) print(a) # [10, 20, 30, 40] — a unchanged print(c) # [10, 20, 30, 40, 50]
Real-life Analogy: Aliasing is like two people sharing the same notebook. If one person writes in it, the other person sees the same writing because they share the same physical notebook.
# Reference Counting import sys x = "Python Programming" print(sys.getrefcount(x)) # Reference count (includes getrefcount arg) y = x print(sys.getrefcount(x)) # Increased by 1 del y print(sys.getrefcount(x)) # Decreased by 1
Examples with Output
Example 1: Inspecting Object Identity and Type
a = 100
b = 100
print("Type of a:", type(a))
print("Type of b:", type(b))
print("id(a):", id(a))
print("id(b):", id(b))
print("a is b:", a is b)
print("a == b:", a == b)
# Output:
# Type of a: <class 'int'>
# Type of b: <class 'int'>
# id(a): 140234866547024
# id(b): 140234866547024
# a is b: True
# a == b: True
Example 2: Mutable vs Immutable Demonstration
# Immutable — new object created
x = 5
print("id(x) before:", id(x))
x = x + 1
print("id(x) after:", id(x))
# Different ids because integers are immutable
# Mutable — same object modified
lst = [1, 2, 3]
print("id(lst) before:", id(lst))
lst.append(4)
print("id(lst) after:", id(lst))
# Same id because lists are mutable
# Output:
# id(x) before: 140234866547120
# id(x) after: 140234866547152
# id(lst) before: 140234866201216
# id(lst) after: 140234866201216
Example 3: Aliasing and Copying
# Aliasing
original = [10, 20, 30]
alias = original
# Shallow Copy
copied = original.copy()
alias.append(40)
copied.append(50)
print("original:", original) # [10, 20, 30, 40]
print("alias:", alias) # [10, 20, 30, 40]
print("copied:", copied) # [10, 20, 30, 50]
# Deep Copy for nested objects
import copy
nested = [[1, 2], [3, 4]]
deep = copy.deepcopy(nested)
deep[0].append(99)
print("nested:", nested) # [[1, 2], [3, 4]] — unchanged
print("deep:", deep) # [[1, 2, 99], [3, 4]]
Example 4: Function Arguments and Mutability
# Immutable argument — no change in original
def change_num(n):
n = n + 10
print("Inside function:", n)
num = 5
change_num(num)
print("Outside function:", num) # Still 5
# Mutable argument — changes affect original
def change_list(lst):
lst.append(100)
print("Inside function:", lst)
my_list = [1, 2, 3]
change_list(my_list)
print("Outside function:", my_list) # [1, 2, 3, 100]
# Output:
# Inside function: 15
# Outside function: 5
# Inside function: [1, 2, 3, 100]
# Outside function: [1, 2, 3, 100]
Example 5: Object Identity with Strings
# String interning — Python may reuse string objects
s1 = "hello"
s2 = "hello"
print(s1 is s2) # True — Python interns small strings
s3 = "hello world!"
s4 = "hello world!"
print(s3 is s4) # May be True or False (implementation-dependent)
# Using str() guarantees a new object
s5 = str("hello")
s6 = str("hello")
print(s5 is s6) # False — str() forces new object
# Empty immutable objects are singletons
t1 = ()
t2 = ()
print(t1 is t2) # True
e1 = frozenset()
e2 = frozenset()
print(e1 is e2) # True
Key Differences: Mutable vs Immutable
| Feature | Mutable | Immutable |
|---|---|---|
| Definition | Value can change after creation | Value cannot change after creation |
| Examples | list, dict, set | int, str, tuple, frozenset |
| id() after modification | Remains the same | Changes (new object created) |
| Safe as dict key | No (unhashable) | Yes (hashable) |
| Aliasing effect | Changes affect all aliases | No shared effect |
Common Mistakes
Mistake 1: Confusing is with ==
# Wrong approach a = [1, 2, 3] b = [1, 2, 3] print(a is b) # False — different objects # Correct approach for value comparison print(a == b) # True — same values
Always use == to compare values and is to check if two variables point to the exact same object.
Mistake 2: Forgetting Aliasing with Mutable Objects
# Unexpected side effect original = [1, 2, 3] copy_list = original # This is aliasing, not copying! copy_list.append(4) print(original) # [1, 2, 3, 4] — original changed! # Use .copy() or [:] for independent copies copy_list = original.copy()
Assigning b = a does not create a copy. Use b = a.copy() or b = a[:] for a shallow copy, and copy.deepcopy(a) for nested structures.
Mistake 3: Trying to Modify Immutable Objects
# This will cause an error
t = (1, 2, 3)
try:
t[0] = 10 # TypeError!
except TypeError as e:
print("Error:", e) # 'tuple' object does not support item assignment
# Workaround: create a new tuple
t = (1, 2, 3)
t = (10,) + t[1:]
print(t) # (10, 2, 3)
Immutable objects cannot be modified in place. You must create a new object with the desired changes.
University Exam Tips
Tip 1: Memorize Mutable vs Immutable Lists
University exams frequently ask: "Which of the following are mutable/immutable in Python?" Remember: int, float, str, tuple, frozenset, bytes = Immutable and list, dict, set, bytearray = Mutable.
Tip 2: Understand Pass by Object Reference
Python uses pass by object reference (not pass by value or pass by reference). When you pass an object to a function, you pass a reference to the object. If the object is mutable, the function can modify it; if immutable, it cannot.
Tip 3: Use id() in Exams to Prove Understanding
In exam answers, demonstrate your understanding by showing id() before and after operations. This proves whether a new object was created or the same object was modified.
Practice Questions
Q1: Explain the difference between is and == with examples.
Answer: is checks object identity (whether two references point to the same object in memory). == checks value equality (whether two objects have the same value).
Q2: Why are strings immutable in Python?
Answer: Strings are immutable for security (preventing accidental modification), memory optimization (string interning/reuse), and dictionary key eligibility (immutable objects are hashable).
Q3: What is aliasing? How can you avoid unintended side effects?
Answer: Aliasing occurs when two variables reference the same object. Use .copy() or slicing [:] for shallow copies and copy.deepcopy() for nested objects.
Q4: What will be the output of the following code?
a = [1, 2, 3] b = a b.append(4) print(a)
Answer: [1, 2, 3, 4] — because b is an alias for a, they point to the same list object.
Q5: Differentiate between mutable and immutable objects with two examples each.
Answer: Mutable: list, dict (value changes without new object). Immutable: int, str (value change creates a new object).
Summary
Everything in Python is an object with an identity, type, and value.
Use id() to get identity and type() to get the type of an object.
is checks identity; == checks value equality.
Mutable objects (list, dict, set) can change value without changing identity.
Immutable objects (int, str, tuple) create new objects on modification.
Aliasing means two variables reference the same object; use .copy() to avoid side effects.
Python uses pass-by-object-reference for function arguments.
Small integers (-5 to 256) are cached and may appear as singletons.