Lists — Complete Deep Dive
Lists — Complete Deep Dive 📋
Python ki sabse important data structure — Lists. Creation se lekar Comprehension tak, Shallow Copy se lekar Time Complexity tak — Basic se Advanced complete deep dive. Har method, har operation, har edge case — detailed examples aur interview Q&A ke saath. Data Insights par.
📑 Is Chapter Mein Kya Sikhenge:
- 🟢 Basic: Introduction, Creating Lists, Indexing, Slicing
- 🟡 Medium: Add Items, Remove Items, Search & Count, Sort & Reverse
- 🔴 Advanced: Shallow vs Deep Copy, List Comprehension, Nested Lists, Built-in Functions, Time Complexity
- 📋 Summary: Complete Methods Cheat Sheet + Comparison Table
1. List Introduction — Definition & Properties 🟢
📘 Definition: A List is an ordered, mutable (changeable), and indexed collection that allows duplicate values. Lists are created using square brackets [] and can hold items of any data type — integers, strings, floats, booleans, and even other lists (nested lists). Lists are the most versatile and most commonly used data structure in Python.
🎯 Samjho Hinglish Mein: List ek dabbon ki line hai — jaise train ke coaches. Har dabba (element) ka ek position number (index) hai. Tum elements add kar sakte ho, hata sakte ho, change kar sakte ho (mutable). Same element baar baar aa sakta hai (duplicates allowed). Aur ek list mein different types ki cheezein rakh sakte ho — number, text, boolean sab ek saath! Python mein list sabse zyada use hone wali structure hai — Pandas DataFrame bhi internally lists par based hai.
📋 List Properties:
| Property | Value | Meaning |
|---|---|---|
| Ordered | ✅ Yes | Elements ka insertion order maintain hota hai |
| Mutable | ✅ Yes | Elements add, remove, change kar sakte ho |
| Indexed | ✅ Yes | Har element ka position number (0, 1, 2...) hai |
| Duplicates | ✅ Allowed | Same value multiple times rakh sakte ho |
| Heterogeneous | ✅ Yes | Different data types ek list mein rakh sakte ho |
| Dynamic Size | ✅ Yes | Size fix nahi — grow/shrink hota hai dynamically |
| Symbol | [ ] (square brackets) | list = [1, 2, 3] |
💬 Interview Q&A:
Q: List ki key properties kya hain?
Ans: List ordered hai (insertion order maintain), mutable hai (elements change ho sakte hain), indexed hai (position number se access), duplicates allow karta hai, heterogeneous hai (mixed data types), aur dynamic size hai (grow/shrink). Square brackets [] se banate hain. Python ki sabse versatile data structure hai.
Q: List mutable hai — iska kya matlab hai?
Ans: Mutable = "change ho sakta hai after creation." List mein elements add, remove, replace, sort — sab kar sakte ho bina naya list banaye. lst[0] = "new" — directly value change. Compare karo string se — string immutable hai (change nahi ho sakta), list mutable hai. Tuple bhi immutable hai — list ka immutable version Tuple hai.
2. Creating Lists — Multiple Ways 🟢
📘 Definition: Lists can be created in multiple ways — using square brackets [], the list() constructor, list(range()), list comprehension, or by splitting a string. Each method has its own use case.
💻 Examples:
# Example 1: All ways to create a list # Method 1: Direct creation with [] numbers = [10, 20, 30, 40, 50] names = ["Jatin", "Priya", "Rahul"] mixed = [1, "Hello", 3.14, True, None] empty = []
# Method 2: list() constructor
from_tuple = list((1, 2, 3)) # Tuple → List
from_string = list("Python") # ['P','y','t','h','o','n']
from_set = list({3, 1, 2}) # Set → List (order not guaranteed)
# Method 3: range()
nums = list(range(1, 11)) # [1, 2, 3, ..., 10]
evens = list(range(0, 21, 2)) # [0, 2, 4, ..., 20]
# Method 4: String split
csv_data = "Jatin,25,Gurugram"
fields = csv_data.split(",") # ['Jatin', '25', 'Gurugram']
print(numbers)
print(from_string)
print(evens)
print(fields)
Output: [10, 20, 30, 40, 50] ['P', 'y', 't', 'h', 'o', 'n'] [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] ['Jatin', '25', 'Gurugram']# Example 2: List of same values (repetition) zeros = [0] * 5 # [0, 0, 0, 0, 0] stars = ["⭐"] * 3 # ['⭐', '⭐', '⭐'] matrix_row = [None] * 4 # [None, None, None, None] print(zeros) print(stars)# Example 3: Nested Lists (list inside list) matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ] employee = ["Jatin", 25, ["Python", "SQL", "Power BI"]] print(employee[2]) # ['Python', 'SQL', 'Power BI'] print(employee[2][1]) # SQL[[0]*3]*3 se matrix MAT banao! Yeh same list ka reference copy karta hai — ek row change karo toh sab change hongi! [[0]*3 for _ in range(3)] use karo — yeh independent rows banata hai. Advanced topic mein detail mein cover karenge. 3. List Indexing — Positive & Negative 🟢
📘 Definition: Each element in a list has a position number called an index. Positive indexing starts from 0 (left to right). Negative indexing starts from -1 (right to left). Since lists are mutable, you can also change values using indexing — list[index] = new_value.
List: ["Jatin", "Priya", "Rahul", "Neha", "Vikram"] (+) 0 1 2 3 4 (-) -5 -4 -3 -2 -1 Access: list[0] = "Jatin",
list[-1] = "Vikram" Change: list[0] = "Amit" → replaces "Jatin" with "Amit"💻 Examples:
# Example 1: Accessing elements fruits = ["Apple", "Banana", "Cherry", "Mango", "Orange"]
print(fruits[0]) # Apple (first item)
print(fruits[2]) # Cherry (third item)
print(fruits[-1]) # Orange (last item)
print(fruits[-2]) # Mango (second last)
# Example 2: Changing values (Mutable!) fruits = ["Apple", "Banana", "Cherry"] print("Before:", fruits) fruits[1] = "Blueberry" # Replace Banana → Blueberry print("After:", fruits) # Before: ['Apple', 'Banana', 'Cherry'] # After: ['Apple', 'Blueberry', 'Cherry'] # Compare with String (immutable): # text = "Hello" # text[0] = "J" → TypeError! Strings immutable# Example 3: IndexError — accessing out of range fruits = ["Apple", "Banana", "Cherry"] # indices: 0, 1, 2 # print(fruits[5]) → IndexError: list index out of range # Safe access: check length first idx = 5 if idx < len(fruits):
print(fruits[idx]) else:
print(f"Index {idx} out of range! Max: {len(fruits)-1}")💬 Interview Q&A:
Q: List[0] aur List[-1] mein kya difference hai?
Ans: List[0] first element access karta hai (left se). List[-1] last element access karta hai (right se). Negative indexing useful hai jab list ki length pata nahi — hamesha [-1] se last element milega. [-2] = second last. Yeh Python ka unique feature hai — C/Java mein negative indexing nahi hota.
4. List Slicing — [start:stop:step] 🟢
📘 Definition: Slicing extracts a portion (sub-list) of a list using [start:stop:step]. Start is inclusive, stop is exclusive. Step defines the increment. Slicing ALWAYS returns a NEW list — original list is unchanged. It works exactly like string slicing (Part 1 mein cover kiya tha).
📋 Slicing Rules:
list[start:stop:step]
• start → inclusive (included in result) — default 0
• stop → exclusive (NOT included) — default len(list)
• step → increment — default 1
list[1:4] → index 1, 2, 3 (4 excluded!)
list[:3] → index 0, 1, 2 (start se 3 tak)
list[2:] → index 2 se end tak
list[:] → full copy of list
list[::2] → every 2nd element
list[::-1] → REVERSED list!
💻 Examples:
# Example 1: Basic slicing nums = [10, 20, 30, 40, 50, 60, 70] print(nums[1:4]) # [20, 30, 40] (index 1,2,3) print(nums[:3]) # [10, 20, 30] (first 3) print(nums[4:]) # [50, 60, 70] (from index 4 to end) print(nums[:]) # [10, 20, 30, 40, 50, 60, 70] (full copy) print(nums[-3:]) # [50, 60, 70] (last 3 elements)# Example 2: Step + Reverse nums = [10, 20, 30, 40, 50, 60, 70] print(nums[::2]) # [10, 30, 50, 70] (every 2nd element) print(nums[1::2]) # [20, 40, 60] (start from 1, every 2nd) print(nums[::-1]) # [70, 60, 50, 40, 30, 20, 10] (REVERSED!) print(nums[::-2]) # [70, 50, 30, 10] (reversed, every 2nd)# Example 3: Slice assignment (modify multiple elements!) fruits = ["Apple", "Banana", "Cherry", "Mango", "Orange"] # Replace index 1,2 with new values fruits[1:3] = ["Blueberry", "Coconut"] print(fruits) # ['Apple', 'Blueberry', 'Coconut', 'Mango', 'Orange'] # Insert without removing (empty slice) nums = [1, 2, 5, 6] nums[2:2] = [3, 4] # Insert 3,4 at index 2 print(nums) # [1, 2, 3, 4, 5, 6] # Delete using slice nums[1:3] = [] # Remove index 1,2 print(nums) # [1, 4, 5, 6]list[::-1] — new list return, original unchanged. (2) list.reverse() — in-place, original changed. (3) list(reversed(list)) — new list return. Interview mein teeno batao — impress karoge! 💬 Interview Q&A:
Q: Slice assignment kya hai? Example do.
Ans: Slice assignment se multiple elements ek saath replace, insert, ya delete kar sakte ho. lst[1:3] = [10, 20] — index 1,2 replace. lst[2:2] = [10, 20] — index 2 par insert (empty slice). lst[1:3] = [] — index 1,2 delete. Yeh list ka powerful mutable feature hai — strings mein slice assignment nahi hota (immutable).
5. Add Items — append(), extend(), insert() 🟡
📘 Definition: append(item) adds ONE item at the END of the list. extend(iterable) adds ALL items from an iterable (list/tuple/set) at the END — merges two lists. insert(index, item) adds ONE item at a SPECIFIC position. All three modify the original list in-place (return None).
🎯 Samjho Hinglish Mein: append() = train ke end mein ek coach jodo. extend() = doosri train ke saare coaches apni train mein jodo (merge). insert() = beech mein ek coach daal do specific position par. append ek item, extend multiple items, insert specific position par ek item. Sabse common mistake: append vs extend confuse karna!
📋 Comparison:
| Method | Adds | Where | Returns |
|---|---|---|---|
| append(item) | ONE item (as single element) | End | None (in-place) |
| extend(iter) | ALL items from iterable | End | None (in-place) |
| insert(i, item) | ONE item at specific index | Specified position | None (in-place) |
💻 Examples:
# Example 1: append() — adds ONE item at end fruits = ["Apple", "Banana"] fruits.append("Cherry") print(fruits) # ['Apple', 'Banana', 'Cherry']
# ⚠️ append() adds LIST as single element — NOT merge!
fruits.append(["Mango", "Orange"])
print(fruits)
# ['Apple', 'Banana', 'Cherry', ['Mango', 'Orange']]
# ↑ Nested list! Not flat! This is the classic mistake!
# Example 2: extend() — merges two lists (flat) fruits = ["Apple", "Banana"] more_fruits = ["Cherry", "Mango", "Orange"] fruits.extend(more_fruits) print(fruits) # ['Apple', 'Banana', 'Cherry', 'Mango', 'Orange'] # ↑ Flat list! All items merged individually! # extend works with any iterable nums = [1, 2] nums.extend((3, 4)) # Tuple nums.extend({5, 6}) # Set nums.extend("78") # String → ['7', '8'] characters! print(nums) # [1, 2, 3, 4, 5, 6, '7', '8']# Example 3: insert() — add at specific position fruits = ["Apple", "Cherry", "Mango"] fruits.insert(1, "Banana") # Insert at index 1 print(fruits) # ['Apple', 'Banana', 'Cherry', 'Mango'] # Insert at beginning fruits.insert(0, "Avocado") print(fruits) # ['Avocado', 'Apple', 'Banana', 'Cherry', 'Mango']append([1,2,3]) vs extend([1,2,3]) — dono BAHUT alag hain! append list ko EK element ke roop mein add karta hai (nested list ban jaata hai). extend list ke ITEMS individually add karta hai (flat rehta hai). Interview mein yeh 100% puchha jaata hai — difference clearly samjho! 💬 Interview Q&A:
Q: append() aur extend() mein kya difference hai?
Ans: append(x) x ko ek SINGLE element ke roop mein list ke end mein add karta hai — agar x list hai toh nested list ban jaata hai. extend(x) x ke saare items INDIVIDUALLY list ke end mein add karta hai — flat list rehta hai. Example: [1,2].append([3,4]) → [1,2,[3,4]]. [1,2].extend([3,4]) → [1,2,3,4]. Merge karna hai = extend. Ek item add karna hai = append.
Q: append() aur insert() mein kya difference hai?
Ans: append() hamesha END mein add karta hai — position control nahi. insert(index, item) SPECIFIC position par add karta hai. insert(0, item) = beginning mein, insert(len(list), item) = end mein (same as append). Performance: append O(1) hai, insert O(n) hai (elements shift karne padte hain).
6. Remove Items — remove(), pop(), del, clear() 🟡
📘 Definition: remove(value) removes the FIRST occurrence of a value (by value, not index). pop(index) removes and RETURNS the item at given index (default: last item). del list[index] deletes item by index (no return). clear() removes ALL items — empty list remains.
📋 Comparison:
| Method | Removes By | Returns Removed? | If Not Found? |
|---|---|---|---|
| remove(value) | Value (first match) | ❌ No (returns None) | ValueError |
| pop(index) | Index position | ✅ Yes (returns removed item) | IndexError |
| del list[i] | Index (or slice) | ❌ No | IndexError |
| clear() | Everything | ❌ No (returns None) | N/A |
💻 Examples:
# Example 1: remove() — by VALUE fruits = ["Apple", "Banana", "Cherry", "Banana"]
fruits.remove("Banana") # Removes FIRST "Banana" only!
print(fruits) # ['Apple', 'Cherry', 'Banana'] ← second Banana still there!
# ⚠️ ValueError if value not found!
# fruits.remove("Mango") → ValueError: list.remove(x): x not in list
# Safe remove — check first
if "Mango" in fruits:
fruits.remove("Mango")
else:
print("Mango not found!")
# Example 2: pop() — by INDEX, returns removed item fruits = ["Apple", "Banana", "Cherry", "Mango"] # pop() without index — removes LAST item last = fruits.pop() print(last) # Mango (returned!) print(fruits) # ['Apple', 'Banana', 'Cherry'] # pop(index) — removes specific index second = fruits.pop(1) print(second) # Banana (returned!) print(fruits) # ['Apple', 'Cherry'] # Practical: Stack behavior (LIFO) stack = [] stack.append("Task 1") stack.append("Task 2") stack.append("Task 3") print(stack.pop()) # Task 3 (last in, first out) print(stack.pop()) # Task 2# Example 3: del and clear() fruits = ["Apple", "Banana", "Cherry", "Mango", "Orange"] # del by index del fruits[1] print(fruits) # ['Apple', 'Cherry', 'Mango', 'Orange'] # del by slice del fruits[1:3] print(fruits) # ['Apple', 'Orange'] # clear() — empty the list (list still exists) fruits.clear() print(fruits) # [] (empty list) # del entire list (list variable destroyed!) # del fruits # print(fruits) → NameError: name 'fruits' is not defined• Know the value, not index:
remove("Banana")• Need the removed item back:
item = pop(2)• Know the index, don't need item:
del list[2]• Remove everything:
clear()• Remove last item (Stack):
pop() (no argument) 💬 Interview Q&A:
Q: remove() aur pop() mein kya difference hai?
Ans: remove(value) VALUE se hatata hai — pehla match hatata hai, kuch return nahi karta. pop(index) INDEX se hatata hai aur removed item RETURN karta hai. remove(value) mein value nahi mili toh ValueError. pop(index) mein index out of range toh IndexError. pop() bina argument ke last item hatata hai — Stack (LIFO) implement karne ke liye perfect.
Q: del aur clear() mein kya farak hai?
Ans: clear() list ke ITEMS hatata hai — empty list [] bachti hai, variable exist karta hai. del list poora list variable DESTROY kar deta hai — variable hi nahi rahega, access karoge toh NameError. del list[i] ek specific item hatata hai index se. clear() = ghar khaali karo. del list = ghar hi tod do.
7. Search & Count — index(), count(), in 🟡
📘 Definition: index(value) returns the index of the FIRST occurrence of a value (ValueError if not found). count(value) returns how many times a value appears (0 if not found — safe). in operator checks membership — returns True/False. not in checks non-membership.
📋 Comparison:
| Method | Returns | If Not Found | Use Case |
|---|---|---|---|
| index(val) | Position (int) | ValueError ❌ | "Kahan hai?" |
| count(val) | Count (int) | 0 (safe ✅) | "Kitni baar hai?" |
| val in list | True / False | False (safe ✅) | "Hai ya nahi?" |
💻 Examples:
# Example 1: index() — find position fruits = ["Apple", "Banana", "Cherry", "Banana", "Mango"]
print(fruits.index("Cherry")) # 2 (first occurrence)
print(fruits.index("Banana")) # 1 (first Banana, not 3)
# Search within range: index(value, start, end)
print(fruits.index("Banana", 2)) # 3 (search from index 2 onwards)
# Safe search — check first with 'in'
target = "Grapes"
if target in fruits:
print(f"Found at index {fruits.index(target)}")
else:
print(f"{target} not in the list")
# Example 2: count() — count occurrences numbers = [1, 2, 3, 2, 4, 2, 5] print(numbers.count(2)) # 3 (appears 3 times) print(numbers.count(10)) # 0 (not found — but no error!) # Practical: Check for duplicates names = ["Jatin", "Priya", "Jatin", "Rahul"] for name in set(names): # set() removes duplicates for checking if names.count(name) > 1:
print(f"Duplicate: {name} ({names.count(name)} times)") # Duplicate: Jatin (2 times)# Example 3: in / not in — membership check fruits = ["Apple", "Banana", "Cherry"] print("Banana" in fruits) # True print("Mango" in fruits) # False print("Mango" not in fruits) # True # Practical: Filter common items between two lists list1 = [1, 2, 3, 4, 5] list2 = [3, 4, 5, 6, 7] common = [x for x in list1 if x in list2] print(f"Common: {common}") # Common: [3, 4, 5] only_in_1 = [x for x in list1 if x not in list2] print(f"Only in list1: {only_in_1}") # Only in list1: [1, 2]in operator list mein O(n) hai — har element check karta hai sequentially. Agar bahut frequent membership checks karni hain (1000+ times) toh list ko set mein convert karo — set(list) — set mein in O(1) hai (instant lookup). Data analysis mein yeh optimization bahut important hai! 💬 Interview Q&A:
Q: Ek list mein duplicates kaise find karo?
Ans: Multiple approaches: (1) count() method: [x for x in set(lst) if lst.count(x) > 1]. (2) Set comparison: original list ki length vs set ki length — agar different toh duplicates hain. (3) Loop: ek seen set maintain karo, agar item already seen mein hai toh duplicate hai. Performance-wise approach 3 best hai O(n), approach 1 worst hai O(n²) kyunki count() itself O(n) hai har element ke liye.
Q: index() safe nahi hai — toh kya use karein?
Ans: Pehle in se check karo, phir index() call karo. Ya try-except use karo: try: idx = lst.index(val) except ValueError: idx = -1. String mein find() method hai jo -1 return karta hai — lekin list mein find() nahi hai. Isliye manual safe check zaroori hai.
Lists — Advanced Deep Dive 🚀
Part 3A ka continuation — ab enter karte hain Lists ki Advanced duniya mein. Sort & Reverse se lekar Time Complexity tak, Shallow Copy se lekar List Comprehension tak, Nested Matrix se lekar Built-in Functions tak — 7 advanced topics, real-world examples aur interview Q&A ke saath. Data Insights par.
📑 Is Chapter Mein Kya Sikhenge:
- 🟡 Medium: Sort & Reverse — sort(), sorted(), reverse()
- 🔴 Advanced: Shallow vs Deep Copy — Reference confusion clear
- 🔴 Advanced: List Comprehension — Basic to Nested
- 🔴 Advanced: Nested Lists — 2D Lists & Matrix Operations
- 🔴 Advanced: Built-in Functions — len, min, max, sum, zip, enumerate, map, filter
- 🔴 Advanced: Time Complexity — Big O of List operations
- 📋 Summary: List vs Tuple vs Set vs Dictionary — Complete Comparison
8. Sort & Reverse — sort(), sorted(), reverse() 🟡
📘 Definition: sort() sorts the list IN-PLACE (modifies original, returns None). sorted(list) returns a NEW sorted list (original unchanged). reverse() reverses the list IN-PLACE. Both sort() and sorted() accept key (custom sort logic) and reverse=True (descending order) parameters.
🎯 Samjho Hinglish Mein: sort() = apni list ko hi arrange kar do (original badal jaayegi). sorted() = ek nayi sorted copy banao (original safe). reverse() = ulta kar do. Sabse important — key parameter — isse tum custom logic de sakte ho — jaise strings ko length se sort karo, ya dictionaries ko age se sort karo. Data analysis mein key ka use bahut hota hai!
📋 sort() vs sorted():
| Feature | sort() | sorted() |
|---|---|---|
| Modifies Original? | ✅ Yes (in-place) | ❌ No (new list) |
| Returns | None | New sorted list |
| Works On | Only lists | Any iterable (list, tuple, set, string) |
| Memory | Less (no new list) | More (creates copy) |
| Syntax | list.sort() | sorted(list) |
💻 Examples:
# Example 1: Basic sort() and sorted()
numbers = [50, 10, 30, 20, 40]
# sort() — modifies original
numbers.sort()
print(numbers) # [10, 20, 30, 40, 50]
# Descending order
numbers.sort(reverse=True)
print(numbers) # [50, 40, 30, 20, 10]
# sorted() — returns new list
original = [3, 1, 4, 1, 5, 9, 2, 6]
new_sorted = sorted(original)
print(original) # [3, 1, 4, 1, 5, 9, 2, 6] ← unchanged!
print(new_sorted) # [1, 1, 2, 3, 4, 5, 6, 9]
Output:
[10, 20, 30, 40, 50]
[50, 40, 30, 20, 10]
[3, 1, 4, 1, 5, 9, 2, 6]
[1, 1, 2, 3, 4, 5, 6, 9]
# Example 2: key parameter — custom sorting
names = ["Jatin", "Ali", "Priyanshu", "Neha"]
# Sort by length
by_length = sorted(names, key=len)
print(by_length) # ['Ali', 'Neha', 'Jatin', 'Priyanshu']
# Sort by last character
by_last = sorted(names, key=lambda x: x[-1])
print(by_last)
# Case-insensitive sort
mixed = ["banana", "Apple", "cherry"]
print(sorted(mixed)) # ['Apple', 'banana', 'cherry'] (A comes first — ASCII)
print(sorted(mixed, key=str.lower)) # ['Apple', 'banana', 'cherry'] (case-insensitive)
# Example 3: Sort list of dictionaries (real-world!)
employees = [
{"name": "Jatin", "age": 25, "salary": 50000},
{"name": "Priya", "age": 30, "salary": 75000},
{"name": "Rahul", "age": 22, "salary": 40000}
]
# Sort by salary (ascending)
by_salary = sorted(employees, key=lambda e: e["salary"])
for emp in by_salary:
print(f"{emp['name']}: ₹{emp['salary']}")
# Sort by age (descending)
by_age_desc = sorted(employees, key=lambda e: e["age"], reverse=True)
# reverse() — in-place reverse
nums = [1, 2, 3, 4, 5]
nums.reverse()
print(nums) # [5, 4, 3, 2, 1]
Output:
Rahul: ₹40000
Jatin: ₹50000
Priya: ₹75000
[5, 4, 3, 2, 1]
result = list.sort()— WRONG! sort() returns None, result mein None aayega. Usesorted()instead.- Mixed types sort karna —
[1, "a", 2]— TypeError! Sirf same type ki cheezein sort ho sakti hain. reverse()aurreverse=Truealag hain — reverse() sirf ulta karta hai (no sort), reverse=True sorted descending order deta hai.
💬 Interview Q&A:
Q: sort() aur sorted() mein kya difference hai?
Ans: sort() list method hai — original list ko IN-PLACE modify karta hai, None return karta hai, sirf lists pe kaam karta hai. sorted() built-in function hai — NEW sorted list return karta hai, original unchanged, kisi bhi iterable pe kaam karta hai (tuple, set, string, dict). Memory-wise sort() efficient hai (no copy), sorted() zyada memory use karta hai. Original preserve karna ho toh sorted(), space bachana ho toh sort().
Q: List of dictionaries ko specific field se kaise sort karo?
Ans: key parameter use karo with lambda function. Example: sorted(employees, key=lambda e: e["salary"]) salary se sort karega. Multiple fields se sort karna ho toh tuple return karo lambda mein: key=lambda e: (e["dept"], -e["salary"]) — pehle department se, phir salary descending se. Yeh Pandas ke sort_values() se pehle Python mein use hota tha, aaj bhi small data ke liye useful.
Q: List reverse karne ke kitne tarike hain?
Ans: 3 main tarike: (1) list.reverse() — in-place, original changed, None return. (2) list[::-1] — slicing, NEW list return, original unchanged. (3) list(reversed(list)) — reversed() iterator return karta hai, list() se convert karo. Interview mein teeno batao — space complexity difference bhi mention karo (reverse() O(1) extra space, baaki O(n)).
9. Copy — Shallow vs Deep Copy 🔴
📘 Definition: = assignment creates a REFERENCE (both point to same list). copy() / list[:] / list.copy() creates a SHALLOW copy — outer list is new, but nested objects are shared. copy.deepcopy() creates a completely INDEPENDENT copy — nested objects also duplicated.
🎯 Samjho Hinglish Mein: Socho tumhare paas ek notebook hai (list). = = kisi ko wohi notebook de diya — dono same book use karenge, ek change karega toh dono ko dikhega. copy() = xerox nikaal ke de diya — outer pages alag, lekin agar andar koi photo chipki hai (nested list) toh photo dono mein same hai. deepcopy() = poori nayi book banake photos bhi copy kar di — ekdum independent!
📋 Comparison:
| Method | Outer List | Nested Objects | Independent? |
|---|---|---|---|
| b = a | Same reference | Same | ❌ No |
| b = a.copy() | NEW list | SHARED (same ref) | ⚠️ Partial |
| b = a[:] | NEW list | SHARED (same ref) | ⚠️ Partial |
| b = deepcopy(a) | NEW list | NEW copies | ✅ Fully |
💻 Examples:
# Example 1: Assignment (=) creates reference — DANGER!
a = [1, 2, 3]
b = a # NOT a copy! Both point to same list!
b.append(4)
print("a:", a) # [1, 2, 3, 4] ← 'a' bhi changed!
print("b:", b) # [1, 2, 3, 4]
print(a is b) # True (same object in memory)
print(id(a), id(b)) # Same memory address
# Example 2: Shallow Copy — outer new, inner shared
original = [[1, 2], [3, 4], [5, 6]]
# 3 ways to create shallow copy
shallow1 = original.copy()
shallow2 = original[:]
shallow3 = list(original)
# Outer list independent — this works fine
shallow1.append([7, 8])
print("original:", original) # unchanged ✅
print("shallow1:", shallow1) # [7,8] added
# BUT — nested lists shared! DANGER!
shallow2[0].append("HACKED")
print("original:", original) # [[1, 2, 'HACKED'], ...] ← changed! 😱
print("shallow2:", shallow2) # [[1, 2, 'HACKED'], ...]
# Example 3: Deep Copy — fully independent
import copy
original = [[1, 2], [3, 4], [5, 6]]
deep = copy.deepcopy(original)
# Modify nested list in deep copy
deep[0].append("SAFE")
print("original:", original) # [[1, 2], [3, 4], [5, 6]] ← unchanged ✅
print("deep:", deep) # [[1, 2, 'SAFE'], [3, 4], [5, 6]]
# The famous [[0]*3]*3 trap
matrix_bad = [[0] * 3] * 3 # DANGER! Same row referenced 3 times
matrix_bad[0][0] = 99
print(matrix_bad) # [[99,0,0], [99,0,0], [99,0,0]] ← all changed!
# Correct way — use list comprehension
matrix_good = [[0] * 3 for _ in range(3)]
matrix_good[0][0] = 99
print(matrix_good) # [[99,0,0], [0,0,0], [0,0,0]] ✅
b = ako copy samajhna — yeh sirf reference hai, dono same list hain!- Nested lists ke saath shallow copy use karna — inner lists shared rehti hain, data corruption ho sakta hai.
[[0]*3]*3se matrix banana — saari rows same reference hoti hain!
💬 Interview Q&A:
Q: Shallow copy aur deep copy mein kya difference hai?
Ans: Shallow copy outer list ka NEW object banata hai, lekin nested objects (inner lists/dicts) ka reference SHARE karta hai — inner change karoge toh original bhi change hoga. list.copy(), list[:], list(original) — teeno shallow copy karte hain. Deep copy outer aur inner sab kuch DUPLICATE karta hai — completely independent copy. copy.deepcopy() use karo. Simple flat list ke liye shallow enough, nested structures ke liye deep zaroori hai.
Q: b = a se copy kyu nahi hoti?
Ans: Python mein = assignment operator sirf REFERENCE assign karta hai — naya object nahi banata. a aur b dono same memory address point karte hain. id(a) == id(b) True aayega. a is b bhi True. Isliye ek change karo toh dono ko dikhega. Copy chahiye toh explicitly copy(), list(), [:], ya deepcopy() use karo. Yeh Python ki fundamental cheez hai — mutable objects (list, dict, set) mein bahut important.
Q: [[0]*3]*3 matrix banane mein kya problem hai?
Ans: [0]*3 ek list [0,0,0] banata hai. Uske baad *3 USI list ka reference 3 baar copy karta hai — 3 alag lists NAHI banate. Isliye matrix[0][0] = 99 karne par saari rows change ho jaati hain. Correct way: [[0]*3 for _ in range(3)] — list comprehension har iteration mein NAYI inner list banata hai. Yeh Python developers ka classic mistake hai — interviewer specifically iski trap check karta hai.
10. List Comprehension — Basic to Advanced 🔴
📘 Definition: List Comprehension is a concise, Pythonic way to create lists using a single line of code. Syntax: [expression for item in iterable if condition]. It combines a for-loop and optional filter into one expression. Faster than traditional for-loops and more readable when used correctly.
🎯 Samjho Hinglish Mein: Multi-line for-loop ka short version = list comprehension. Ek line mein loop + condition + transformation — sab kuch! Example: 5 numbers ka square chahiye — traditional way mein 3-4 lines lagti hain, comprehension mein 1 line! Speed bhi zyada, code bhi clean. Pandas aane se pehle data analysis ka main tool tha yeh.
📋 Syntax Patterns:
Basic: [expr for item in iterable]
Filter: [expr for item in iterable if condition]
If-Else: [expr1 if condition else expr2 for item in iterable]
Nested: [expr for i in iter1 for j in iter2]
2D: [[expr for j in inner] for i in outer]
💻 Examples:
# Example 1: Traditional loop vs Comprehension
# Traditional way — 3 lines
squares = []
for x in range(1, 6):
squares.append(x ** 2)
print(squares) # [1, 4, 9, 16, 25]
# List comprehension — 1 line!
squares = [x ** 2 for x in range(1, 6)]
print(squares) # [1, 4, 9, 16, 25]
# More examples
cubes = [x ** 3 for x in range(1, 6)]
upper = [name.upper() for name in ["jatin", "priya"]]
lengths = [len(word) for word in ["Hi", "Hello", "Python"]]
print(upper) # ['JATIN', 'PRIYA']
print(lengths) # [2, 5, 6]
# Example 2: With filter (if condition)
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Only even numbers
evens = [x for x in numbers if x % 2 == 0]
print(evens) # [2, 4, 6, 8, 10]
# Squares of even numbers
even_squares = [x**2 for x in numbers if x % 2 == 0]
print(even_squares) # [4, 16, 36, 64, 100]
# Filter names starting with 'J'
names = ["Jatin", "Priya", "Jai", "Rahul", "Jyoti"]
j_names = [n for n in names if n.startswith("J")]
print(j_names) # ['Jatin', 'Jai', 'Jyoti']
# If-Else (before for) — categorize each element
labels = ["Even" if x % 2 == 0 else "Odd" for x in range(1, 6)]
print(labels) # ['Odd', 'Even', 'Odd', 'Even', 'Odd']
# Example 3: Nested Comprehension (Advanced!)
# All (i, j) pairs where i in range(3), j in range(3)
pairs = [(i, j) for i in range(3) for j in range(3)]
print(pairs)
# [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), (2,2)]
# Flatten a 2D list
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Create 2D matrix (3x3 with zeros)
zeros_matrix = [[0 for _ in range(3)] for _ in range(3)]
print(zeros_matrix) # [[0,0,0], [0,0,0], [0,0,0]]
# Multiplication table (5x5)
mult_table = [[i*j for j in range(1, 6)] for i in range(1, 6)]
for row in mult_table:
print(row)
Output:
[1, 2, 3, 4, 5]
[2, 4, 6, 8, 10]
[3, 6, 9, 12, 15]
[4, 8, 12, 16, 20]
[5, 10, 15, 20, 25]
• ✅ Simple transformations aur filters ke liye — clean aur fast
• ✅ Data analysis mein — quick data cleaning
• ❌ Complex logic (3+ conditions, side effects) — traditional loop use karo
• ❌ Debug karna mushkil ho toh — readability > brevity
• 💡 Rule: Agar 1 line clean nahi lagti, toh for-loop better hai
ifki position — filter ke liyeforke BAAD, if-else ke liyeforke PEHLE!- Nested comprehension mein order galat karna — outer loop pehle, inner baad mein likho.
- Bahut complex comprehension — 2 lines ka for-loop 1 line ki uncomprehensible comprehension se better hai.
💬 Interview Q&A:
Q: List comprehension for-loop se fast kyu hai?
Ans: List comprehension internally C-level pe optimized hota hai — Python interpreter isse ek single expression ki tarah execute karta hai. For-loop mein har iteration mein append() method call hoti hai — jo method lookup + function call overhead add karti hai. Benchmark: 1 million items ke liye comprehension ~30-40% faster hota hai for-loop se. Lekin readability important hai — sirf speed ke liye complex comprehension mat likho.
Q: if filter aur if-else comprehension mein kya farak hai?
Ans: Filter (if): [x for x in lst if x > 5] — if for ke BAAD hai — sirf woh elements aayenge jo condition satisfy karte hain. If-Else: ["big" if x > 5 else "small" for x in lst] — if-else for ke PEHLE hai — HAR element aayega, but transformed based on condition. Filter mein items skip hote hain, if-else mein sab process hote hain.
Q: 2D matrix ko flatten kaise karo comprehension se?
Ans: [num for row in matrix for num in row] — outer loop pehle (row select karo), inner loop baad mein (row ke items lo). Order left-to-right hai — jaise nested for-loop likhte ho. Example: [[1,2],[3,4]] → [1,2,3,4]. Alternative: sum(matrix, []) (slower), ya itertools.chain(*matrix) (memory efficient), ya NumPy: arr.flatten() (fastest for numeric data).
11. Nested Lists — 2D Lists & Matrix Operations 🔴
📘 Definition: A Nested List is a list that contains other lists as its elements. 2D lists (list of lists) are commonly used to represent matrices, tables, grids, and multi-dimensional data. Access: matrix[row][col]. Use nested loops or comprehensions to iterate.
🎯 Samjho Hinglish Mein: Nested list = list ke andar list. Excel ki tarah socho — rows aur columns. Har row ek list hai, aur poori table bhi ek list hai. matrix[0] = first row, matrix[0][2] = first row ka third column. Data analysis mein tables aisa hi represent hote hain. Pandas DataFrame internally kuch aisa hi hota hai — bas usmein indexing aur labels bhi hote hain.
💻 Examples:
# Example 1: Creating and accessing 2D lists
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# Access individual elements
print(matrix[0]) # [1, 2, 3] (first row)
print(matrix[1][2]) # 6 (row 1, col 2)
print(matrix[-1][-1]) # 9 (last row, last col)
# Modify element
matrix[0][0] = 99
print(matrix[0]) # [99, 2, 3]
# Get dimensions
rows = len(matrix)
cols = len(matrix[0])
print(f"{rows} rows x {cols} cols") # 3 rows x 3 cols
# Example 2: Iterating through 2D list
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# Method 1: Nested for loop
for row in matrix:
for num in row:
print(num, end=" ")
print() # new line after each row
# Method 2: Using indices
for i in range(len(matrix)):
for j in range(len(matrix[i])):
print(f"matrix[{i}][{j}] = {matrix[i][j]}")
# Method 3: enumerate for index tracking
for i, row in enumerate(matrix):
for j, val in enumerate(row):
if val > 5:
print(f"Big value {val} at ({i},{j})")
# Example 3: Matrix Operations
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# 1. Transpose (rows ↔ columns)
transpose = [[row[i] for row in matrix] for i in range(3)]
print("Transpose:", transpose)
# [[1,4,7], [2,5,8], [3,6,9]]
# 2. Sum of all elements
total = sum(sum(row) for row in matrix)
print("Total sum:", total) # 45
# 3. Row sums and column sums
row_sums = [sum(row) for row in matrix]
col_sums = [sum(matrix[i][j] for i in range(3)) for j in range(3)]
print("Row sums:", row_sums) # [6, 15, 24]
print("Col sums:", col_sums) # [12, 15, 18]
# 4. Real-world: Employee data table
employees = [
["Jatin", 25, 50000],
["Priya", 30, 75000],
["Rahul", 28, 60000]
]
# Total salary
total_sal = sum(emp[2] for emp in employees)
print(f"Total salary: ₹{total_sal}") # ₹185000
# Names of employees above 27
senior = [emp[0] for emp in employees if emp[1] > 27]
print(f"Senior employees: {senior}") # ['Priya', 'Rahul']
matrix[0,0]— NumPy syntax! Python lists meinmatrix[0][0]use karo.- Uneven rows —
[[1,2,3], [4,5]]jagged list hai, matrix operations fail ho sakti hain. - Real matrix computation ke liye Python list slow hai — NumPy use karo (10-100x faster).
💬 Interview Q&A:
Q: 2D list ka transpose kaise karo?
Ans: Transpose matlab rows ko columns aur columns ko rows banana. 3 ways: (1) List comprehension: [[row[i] for row in matrix] for i in range(len(matrix[0]))]. (2) zip() + list: list(zip(*matrix)) — most Pythonic! But tuples return karta hai. (3) NumPy: np.array(matrix).T — fastest for numeric matrices. Interview mein zip(*matrix) batao — impress karoge.
Q: Nested list ke liye Python list vs NumPy — kab kya use karein?
Ans: Python list tab use karo jab: (1) Small data hai (<1000 elements), (2) Mixed data types hain (string + int + bool), (3) Dynamic size chahiye (frequent append/remove). NumPy array tab use karo jab: (1) Numerical computation heavy hai, (2) Large data (10K+ elements), (3) Mathematical operations chahiye (matrix multiplication, transpose, statistics), (4) Same dtype hai. Data science mein NumPy default choice hai — 10-100x faster.
12. Built-in Functions — len, min, max, sum, zip, enumerate, map, filter 🔴
📘 Definition: Python provides several built-in functions that work with lists (and other iterables). These functions are highly optimized and should be preferred over manual loops. Categories: Aggregation (len, sum, min, max), Iteration helpers (zip, enumerate), Functional (map, filter).
📋 Function Cheat Sheet:
| Function | Purpose | Example |
|---|---|---|
| len(lst) | Count elements | len([1,2,3]) → 3 |
| sum(lst) | Sum of numbers | sum([1,2,3]) → 6 |
| min(lst) / max(lst) | Smallest / largest | max([3,1,4]) → 4 |
| zip(a, b) | Pair two lists | zip([1,2],[a,b]) → [(1,a),(2,b)] |
| enumerate(lst) | Index + value | (0,'a'), (1,'b')... |
| map(fn, lst) | Apply fn to each | map(str, [1,2]) → ['1','2'] |
| filter(fn, lst) | Keep items where fn=True | filter(is_even, [1,2,3]) |
| any() / all() | Boolean check | all([True, True]) → True |
💻 Examples:
# Example 1: Aggregation functions
sales = [1200, 850, 2100, 1500, 950, 1750]
print(f"Count: {len(sales)}") # 6
print(f"Total: ₹{sum(sales)}") # ₹8350
print(f"Min: ₹{min(sales)}") # ₹850
print(f"Max: ₹{max(sales)}") # ₹2100
print(f"Average: ₹{sum(sales)/len(sales):.2f}") # ₹1391.67
# min/max with key parameter
words = ["Python", "Java", "C", "JavaScript"]
print(max(words, key=len)) # JavaScript (longest)
print(min(words, key=len)) # C (shortest)
# any() and all()
scores = [85, 90, 78, 92]
print(all(s >= 70 for s in scores)) # True (sab pass)
print(any(s >= 90 for s in scores)) # True (koi 90+ hai)
# Example 2: zip() and enumerate()
# zip() — pair two/more lists
names = ["Jatin", "Priya", "Rahul"]
ages = [25, 30, 28]
cities = ["Delhi", "Mumbai", "Pune"]
for name, age, city in zip(names, ages, cities):
print(f"{name} ({age}) from {city}")
# Create dict from two lists
data = dict(zip(names, ages))
print(data) # {'Jatin': 25, 'Priya': 30, 'Rahul': 28}
# enumerate() — index + value together
fruits = ["Apple", "Banana", "Cherry"]
for idx, fruit in enumerate(fruits):
print(f"{idx}: {fruit}")
# Custom start index
for idx, fruit in enumerate(fruits, start=1):
print(f"{idx}. {fruit}") # 1. Apple, 2. Banana...
# Example 3: map() and filter()
# map() — apply function to each element
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x**2, numbers))
print(squares) # [1, 4, 9, 16, 25]
# Convert list of strings to int
str_nums = ["10", "20", "30"]
int_nums = list(map(int, str_nums))
print(int_nums) # [10, 20, 30]
# filter() — keep elements where condition True
nums = [1, 2, 3, 4, 5, 6, 7, 8]
evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens) # [2, 4, 6, 8]
# map + filter together
sales = [1200, 500, 2100, 800, 1500]
# Get 10% tax on sales > 1000
tax = list(map(lambda x: x * 0.1, filter(lambda x: x > 1000, sales)))
print(tax) # [120.0, 210.0, 150.0]
# Modern Pythonic way — list comprehension
tax_pythonic = [x * 0.1 for x in sales if x > 1000]
print(tax_pythonic) # [120.0, 210.0, 150.0] — same result, cleaner!
•
zip() stops at the shortest list — zip([1,2,3], [a,b]) → 2 pairs only•
enumerate() for-loop mein index chahiye toh use karo — range(len()) se better•
map() aur filter() ki jagah aajkal list comprehension preferred hai (more readable)•
sum(), min(), max() generators pe kaam karte hain — memory efficient
💬 Interview Q&A:
Q: zip() aur enumerate() mein kya farak hai?
Ans: zip() DO ya zyada lists ko pair karta hai — zip(names, ages) → [(name1, age1), (name2, age2)...]. Parallel iteration ke liye use hota hai. enumerate() EK list ke saath index add karta hai — enumerate(list) → [(0, item1), (1, item2)...]. Index tracking ke liye. Simple rule: multiple lists → zip, single list + index → enumerate.
Q: map/filter vs list comprehension — kaunsa better hai?
Ans: List comprehension preferred hai aajkal — more readable, Pythonic, aur single expression mein map + filter dono kar sakta hai. Example: [x*2 for x in lst if x>0]. map/filter tab better hain jab: (1) Existing named function pass karni hai (map(str, lst)), (2) Lazy evaluation chahiye (memory efficient — iterator return karte hain), (3) Functional programming style follow karna hai. Performance similar hai — readability decide karti hai.
Q: any() aur all() ka use case kya hai?
Ans: all(iter) True return karta hai jab SAB elements True hon (empty iterable pe bhi True — vacuous truth). any(iter) True return karta hai jab KOI EK bhi True ho. Real-world: all(s >= 70 for s in scores) — sab students pass hain? any(err in errors for err in critical) — koi critical error hai? Short-circuit evaluation karte hain — jaise hi answer clear ho, ruk jaate hain (efficient).
13. List Performance — Time Complexity (Big O) 🔴
📘 Definition: Time Complexity (Big O notation) describes how the execution time of an operation grows with the size of input (n). For lists, different operations have different time complexities. Understanding this helps write efficient code, especially for large datasets.
🎯 Samjho Hinglish Mein: Time Complexity = "kaam kitna time lega jab data badh jaaye?" O(1) = constant (data kitna bhi bada ho, same time — jaise index access). O(n) = linear (data double hoga toh time bhi double — jaise search). O(n²) = quadratic (data double hoga toh time 4x — jaise nested loop). Interview mein aur data science mein critical concept — 1000 items pe fast code 1 million items pe crash ho sakta hai!
📋 List Operations — Time Complexity:
| Operation | Complexity | Reason |
|---|---|---|
| list[i] (access) | O(1) ⚡ | Direct memory access |
| list[i] = x (assign) | O(1) ⚡ | Direct memory write |
| append(x) | O(1) amortized ⚡ | End mein add, occasional resize |
| pop() (last) | O(1) ⚡ | Last element remove — no shift |
| insert(0, x) | O(n) 🐢 | Sab elements shift karne padte hain |
| pop(0) | O(n) 🐢 | Sab elements shift karne padte hain |
| remove(x) | O(n) 🐢 | Search + shift |
| x in list | O(n) 🐢 | Sequential search |
| index(x) | O(n) 🐢 | Sequential search |
| len(list) | O(1) ⚡ | Length stored internally |
| sort() | O(n log n) ⚙️ | Timsort algorithm |
| copy() / list[:] | O(n) 🐢 | Har element copy karna |
| reverse() | O(n) 🐢 | Har element swap |
💻 Practical Examples:
# Example 1: append() vs insert(0) — HUGE difference!
import time
# Fast: append at end — O(1)
start = time.time()
lst = []
for i in range(100000):
lst.append(i)
print(f"append: {time.time()-start:.4f}s") # ~0.01s
# Slow: insert at start — O(n)
start = time.time()
lst = []
for i in range(100000):
lst.insert(0, i) # Every insert shifts all!
print(f"insert(0): {time.time()-start:.4f}s") # ~2-3s (300x slower!)
# Better: append then reverse
start = time.time()
lst = []
for i in range(100000):
lst.append(i)
lst.reverse()
print(f"append+reverse: {time.time()-start:.4f}s") # ~0.01s
# Example 2: list `in` O(n) vs set `in` O(1)
import time
data = list(range(1000000))
data_set = set(data)
# Search in list — O(n)
start = time.time()
for _ in range(1000):
999999 in data
print(f"list search: {time.time()-start:.4f}s") # ~10s
# Search in set — O(1)
start = time.time()
for _ in range(1000):
999999 in data_set
print(f"set search: {time.time()-start:.4f}s") # ~0.0001s (100000x faster!)
# Rule: Frequent lookups → convert to set
# Example 3: Efficient patterns
# ❌ BAD: O(n²) — nested loop with list.count()
data = [1, 2, 3, 2, 1, 4] * 1000
duplicates = [x for x in set(data) if data.count(x) > 1] # O(n²)!
# ✅ GOOD: O(n) — using dict/Counter
from collections import Counter
counts = Counter(data)
duplicates = [x for x, c in counts.items() if c > 1] # O(n)
# ❌ BAD: O(n) queue with pop(0)
queue = list(range(10000))
while queue:
item = queue.pop(0) # O(n) each time!
# ✅ GOOD: use collections.deque for queue
from collections import deque
queue = deque(range(10000))
while queue:
item = queue.popleft() # O(1) each time!
insert(0, x)aurpop(0)— front operations slow hain, deque use karox in listin loop — large lists ke liye set mein convert karolist.count()in loop — Counter use karo O(n²) → O(n)- Concatenation in loop:
lst = lst + [x]— O(n) each! append() use karo
💬 Interview Q&A:
Q: append() O(1) amortized kaise hai?
Ans: Python list internally dynamic array hai — memory pre-allocate karta hai extra space ke saath. Jab space bhar jaata hai toh double size ka naya array banata hai aur old elements copy karta hai (yeh operation O(n) hai). But yeh rarely hota hai — mostly append O(1) hai. Overall AVERAGE (amortized) analysis mein O(1) aata hai. Jaise 1000 appends mein sirf 10 resize hongi.
Q: insert(0) aur pop(0) slow kyu hain?
Ans: List internally contiguous memory mein store hoti hai. Jab tum index 0 pe insert karte ho, saare existing elements ko ek position AAGE shift karna padta hai — n elements ke liye n operations = O(n). Same for pop(0) — saare elements PICHE shift hote hain. Solution: collections.deque use karo — yeh doubly-linked list based hai, front aur back dono end pe O(1) operations support karta hai (appendleft(), popleft()).
Q: List vs Set — membership check ke liye kaunsa fast hai aur kyu?
Ans: Set is 100-1000x faster for membership check (x in ...). Reason: List sequential search karti hai — O(n). Set internally HASH TABLE use karta hai — element ka hash calculate karke direct memory location pe check karti hai — O(1) constant time. Rule: agar kisi list mein frequently in check karna hai (loops mein especially), pehle set mein convert karo: data_set = set(data_list). Small one-time check ke liye list bhi theek hai.
14. List vs Other Structures — Complete Comparison 📋
📘 Definition: Python provides 4 main built-in data structures — List, Tuple, Set, and Dictionary. Each has unique properties and use cases. Choosing the right structure impacts performance, memory, and code clarity significantly.
📋 Complete Comparison Table:
| Feature | List [ ] | Tuple ( ) | Set { } | Dict {k:v} |
|---|---|---|---|---|
| Ordered | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes (3.7+) |
| Mutable | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |
| Duplicates | ✅ Allowed | ✅ Allowed | ❌ No | Keys: No, Values: Yes |
| Indexed | ✅ Yes (int) | ✅ Yes (int) | ❌ No | ✅ Yes (key) |
| Search (in) | O(n) 🐢 | O(n) 🐢 | O(1) ⚡ | O(1) ⚡ |
| Memory | Medium | Less ⚡ | More | More |
| Syntax | [1, 2, 3] | (1, 2, 3) | {1, 2, 3} | {"a": 1} |
| Use Case | Ordered data, frequent changes | Fixed data, coordinates | Unique items, fast lookup | Key-value pairs |
💻 When to Use What — Practical Guide:
# USE LIST
when:
# ✅
Order matters
# ✅ Elements can repeat
# ✅ Need to modify (add/remove/change)
# ✅ Index-based access needed
students_marks = [85, 90, 78, 85, 92] # Marks with duplicates,
order matters
# USE TUPLE
when:
# ✅ Data won't change (immutable)
# ✅ Coordinates, fixed pairs
# ✅ Dictionary keys chahiye (list nahi ho sakti)
# ✅ Memory efficient
coordinates = (28.6, 77.2) # Delhi lat, long — fixed!
rgb = (255, 100, 50) # Color
values — fixed!
# USE
SET
when:
# ✅ Only unique items
# ✅ Fast membership test
# ✅
Set operations (union, intersection)
unique_visitors = {"user1", "user2", "user3"} # No duplicates!
common =
set(list_a) &
set(list_b) # Intersection
# USE DICT
when:
# ✅ Key-value mapping
# ✅ Fast lookup by key
# ✅ JSON-like data
employee = {"name": "Jatin", "age": 25, "salary": 50000}
# Real-world: Same data, different structures
# Scenario: Employee names to store
# If order matters & duplicates possible → LIST
attendance = ["Jatin", "Priya", "Jatin", "Rahul"] # Order of arrival
# If unique names only → SET
unique_emp = {"Jatin", "Priya", "Rahul"} # Unique employees
# If additional info needed → DICT
employees = {
"Jatin": {"dept": "IT", "salary": 50000},
"Priya": {"dept": "HR", "salary": 45000}
}
# If constant reference data → TUPLE
DEPARTMENTS = ("IT", "HR", "Finance", "Marketing") # Won't change
• Order + Change + Duplicates → LIST
• Order + Fixed + Duplicates → TUPLE
• Unique + Fast search → SET
• Key-Value mapping → DICT
• 💡 Rule: Pehle requirement samjho, phir structure choose karo — wrong choice = performance loss!
💬 Interview Q&A:
Q: List vs Tuple — kab kya use karein?
Ans: List mutable hai — jab data change hoga (add/remove/modify). Example: shopping cart, todo list, dynamic data. Tuple immutable hai — jab data FIX hai. Example: coordinates (lat, long), RGB color, database records (id, name, email). Tuple faster hai list se (less overhead), memory bhi kam use karti hai. Dictionary keys mein tuple use ho sakti hai, list nahi (hashable requirement). Rule: change hona hai = list, nahi = tuple.
Q: List vs Set — kaunsa faster hai aur kab kaunsa use karein?
Ans: Set faster hai lookup mein — x in set is O(1), x in list is O(n). Set duplicates automatically remove karta hai. USE LIST jab: order important hai, duplicates chahiye, index se access karna hai. USE SET jab: sirf unique items chahiye, fast membership check, set operations (union, intersection, difference). Example: list(set(data)) — duplicates hatane ka one-liner.
Q: List vs Dict — data storage ke liye kaunsa better hai?
Ans: Depends on access pattern. List tab better hai jab sequential access hai (iteration, ordering matters). Dict tab better hai jab identifier se access karna hai (key-based lookup). Example: 100 employees ki list mein "Jatin" ki salary chahiye — list mein O(n) loop lagega, dict mein O(1) direct access — employees["Jatin"]. Modern Python (3.7+) mein dict bhi ordered hai, isliye dict ki utility badh gayi hai.
Next: Python Handbook — Part 4
Agle part mein hum cover karenge: Tuples — Complete Deep Dive. Creation, indexing, packing/unpacking, immutability, named tuples, use cases — sab kuch detail mein. Lists ka immutable version — data science mein constants store karne ka best tarika. Part 3A (Lists Basic) aur Part 3B (Lists Advanced) Data Insights par available hain.
Happy Learning & Keep Coding! 🚀
💬 Comments (0)
Loading comments...