- Day : Saturday
- Date : 2025-09-13
- Time : 11:16
- Tags : #python #Revised #lists
- References : [[RevisedNotes]], [[ImportantQuestionsLists1]]
- Branch of : Python > RevisedNotes > RevisedNotesLists
- Author : dx
• len(list) : gives their length of list TypeError if not iterable
• list(iterable) : it will create a list , without arg create a empty list, if str as arg it make list of each character as a element , if list(dict) then it will make list of keys.um if did list([1,2,3]) then give [1,2, 3]
• sorted(list,key=len,reverse=True) : it will always return a new list in ascending by default if reverse=True then in DESCENDING order , if we add key as arg it will sort it as per key like
Give TypeError if of mixed datatype
# 1. Default sorting
sorted([3, 1, 2]) # [1, 2, 3]
# 2. Sort by length of strings
sorted(["python", "is", "great"], key=len) # ['is', 'great', 'python']
# 3. Case-insensitive sort
sorted(["Banana", "apple", "Cherry"], key=str.lower) # ['apple', 'Banana', 'Cherry']
# 4. Sort numbers by absolute value
sorted([-4, 2, -1, 3], key=abs) # [-1, 2, 3, -4]
# 5. Sort tuples by 2nd element
sorted([(1, 3), (2, 1), (3, 2)], key=lambda x: x[1]) # [(2, 1), (3, 2), (1, 3)]
# 6. Sort by multiple criteria (2nd element, then 1st element)
sorted([("apple", 3), ("banana", 2), ("cherry", 2)], key=lambda x: (x[1], x[0]))
# [('banana', 2), ('cherry', 2), ('apple', 3)]
# 7. Sort by last character of string
sorted(["dog", "cat", "elephant"], key=lambda s: s[-1]) # ['elephant', 'dog', 'cat']
# 8. Sort list of dicts by a specific key
data = [{"name": "Alice", "age": 25}, {"name": "Bob", "age": 20}]
sorted(data, key=lambda d: d["age"])
# [{'name': 'Bob', 'age': 20}, {'name': 'Alice', 'age': 25}]
# 9. Sort objects by attribute
class Student:
def __init__(self, name, marks):
self.name = name
self.marks = marks
students = [Student("Alice", 85), Student("Bob", 95), Student("Charlie", 90)]
[s.name for s in sorted(students, key=lambda s: s.marks)]
# ['Alice', 'Charlie', 'Bob']
# 10. Sort strings by numeric value inside
sorted(["item12", "item3", "item2"], key=lambda s: int(s[4:]))
# ['item2', 'item3', 'item12']
# 11. Sort by word count in string
sorted(["a quick fox", "hello", "two words here"], key=lambda s: len(s.split()))
# ['hello', 'a quick fox', 'two words here']
# 12. Reverse + key (largest first)
sorted([3, 1, 4, 2], key=lambda x: x, reverse=True) # [4, 3, 2, 1]
# 13. Sort dict keys alphabetically
sorted({"b": 2, "a": 1, "c": 3}) # ['a', 'b', 'c']
# 14. Sort dict items by value
sorted({"b": 2, "a": 1, "c": 3}.items(), key=lambda x: x[1])
# [('a', 1), ('b', 2), ('c', 3)]
# 15. Sort with operator.itemgetter
from operator import itemgetter
sorted([(1, 3), (2, 1), (3, 2)], key=itemgetter(1))
# [(2, 1), (3, 2), (1, 3)]
# 16. Sort with operator.attrgetter
from operator import attrgetter
sorted(students, key=attrgetter("marks"))
# [Student(Alice,85), Student(Charlie,90), Student(Bob,95)]• sum(list,start=0) : it will calculate the sum of iterable present and if of different datatype it will give error TypeError and if list empty it will not give 0 not error, and we can add start value in it what it will do is it will be added to the sum of the iterable result
• min(iterable,*args ,key=none,default=0), max() : it will give ValueError if iterable is empty we can set default as it will not give valueerror then , it will give TypeError if of mixed datatype or non iterable , we can use it to calculate the min,max of list we can use unpacking operator in it * , we can use key as arg to manipulate the being used values , in list of booleans the min is False and max is True , we can also use min(* a,* b) as to unpack iterables a,b and then compare it
• enumerate(iterable, start=0) : it will do is it will return the enumerate object that contains index,value as a pair in tuple if we add a start value then it will start counting the index as from that value and give upto full elements even if it is overflowing the original index , we can access it by for loop as : for i,val in enumerate(list,start=1) , can be used with zip function as :
for i, (n, a) in enumerate(zip(names, ages), start=100):
print(i, n, a),if it is empty does not return error will give empty enu obj, it will raise TypeError if start is not int
• reversed(iterable) : it takes only iterable as arg no extra arg, it gives reversed iterator that can be further be converted int list or tuple, it gives TypeError if not iterable
• zip(*iterables) or zip(list1,list2,……) : Returns a zip object (an iterator) of tuples, where each tuple contains the i-th elements of the input iterables.Stops at the shortest iterable. can be used like this
pairs = [('Alice', 25), ('Bob', 30)]
names, ages = zip(*pairs) , no errors , if non iterable TypeError• map(function,iterables) : it returns map object which will contains the elements of iterables after applying a specific function to each element of it , no error , only TypeError if non iterable
nums = [1, 2, 3, 4]
def square(x):
return x**2
result = map(square, nums)
print(list(result)) # [1, 4, 9, 16]nums = [1, 2, 3, 4]
print(list(map(lambda x: x*2, nums))) # [2, 4, 6, 8]a = [1, 2, 3]
b = [4, 5, 6]
result = map(lambda x, y: x + y, a, b)
print(list(result)) # [5, 7, 9]nums = [1.1, 2.2, 3.3]
print(list(map(int, nums))) # [1, 2, 3]
print(list(map(str, nums))) # ['1.1', '2.2', '3.3']words = ["1", "2", "3"]
print(list(map(int, words))) # [1, 2, 3]nums = [0, 1, 2, 3]
print(list(map(bool, nums))) # [False, True, True, True]nums = [1, 4, 2, 3]
# square then sort descending
print(sorted(map(lambda x: x**2, nums), reverse=True))
# [16, 9, 4, 1]nums = [1, 2, 3]
for i, val in enumerate(map(lambda x: x*10, nums)):
print(i, val)
# 0 10
# 1 20
# 2 30nums = [1,2,3]
print(list(map(str, nums))) # ['1','2','3']
print(tuple(map(str, nums))) # ('1','2','3')
print(set(map(str, nums))) # {'1','3','2'} (unordered)• Non-iterable → TypeError:
map(lambda x: x*2, 5) # ❌ TypeError• Multiple iterables → stops at shortest length:
map(lambda x,y: x+y, [1,2], [10]) # only first elements used• function=None → returns original elements:
nums = [1,2,3]
print(list(map(None, nums))) # ❌ TypeError in Python 3• filter(function ,iterable) : it will give out filter object that contains the element who verified the function it filters the true elements of iterable as per function , no error, TypeError if not iterable
map(func, iterable) → applies func to all elements, returns values (truthy or not), same length as iterable; filter(func, iterable) → keeps elements where func returns truthy, may be shorter than iterable.
filter(function, iterable)
• Applies a function to each element of an iterable.
• Returns only the elements where function returns True.
• Returns a filter object (iterator).
nums = [1, 2, 3, 4, 5]
def is_even(x):
return x % 2 == 0
result = filter(is_even, nums)
print(list(result)) # [2, 4]nums = [1, 2, 3, 4, 5]
print(list(filter(lambda x: x>3, nums))) # [4, 5]data = [0, 1, "", "Hello", None, "Python"]
print(list(filter(None, data)))
# [1, 'Hello', 'Python'] → filters out falsy values (0, "", None)words = ["apple", "bat", "cat", "ant"]
print(list(filter(lambda w: len(w)==3, words)))
# ['bat', 'cat', 'ant']• Unlike map(), filter() works only with one iterable.
• If you want multiple, combine with zip():
a = [1,2,3]
b = [4,5,6]
result = filter(lambda x: x[0] + x[1] > 5, zip(a,b))
print(list(result)) # [(2,4),(3,3),(3,6)]• Empty iterable → returns empty iterator:
print(list(filter(lambda x: x>0, []))) # []• Non-iterable → TypeError:
filter(lambda x: x>0, 5) # ❌ TypeErrornums = [1, 2, 3, 4, 5]
# double the numbers >2
print(list(map(lambda x:x*2, filter(lambda x:x>2, nums))))
# [6, 8, 10]
# sort filtered elements
print(sorted(filter(lambda x: x%2==0, nums)))
# [2, 4]• Supports multiple iterables.
• The function must accept the same number of arguments as iterables.
• Iteration stops at the shortest iterable.
Example
a = [1, 2, 3]
b = [4, 5, 6, 7]
result = map(lambda x, y: x + y, a, b)
print(list(result)) # [5, 7, 9] → stops at shortest (a)• Works with any number of iterables:
x = [1,2]
y = [10,20]
z = [100,200]
print(list(map(lambda a,b,c: a+b+c, x,y,z))) # [111, 222]• Does NOT support multiple iterables directly.
• Only accepts one iterable.
• If you want to filter based on multiple sequences, combine them using zip():
Example
a = [1, 2, 3]
b = [4, 5, 6]
result = filter(lambda x: x[0] + x[1] > 5, zip(a, b))
print(list(result)) # [(2,4), (3,3), (3,6)]• Here, zip(a,b) creates tuples (a_i, b_i) which filter() can process.
| Function | Multiple Iterables? | Notes |
|----------|-------------------------|-----------|
| map() | ✅ Yes | Function must accept same number of args; stops at shortest iterable |
| filter() | ❌ No | Must combine iterables manually (e.g., with zip()) |
So basically:
• map(f, a, b, c) → works natively.
• filter(f, a, b) → must do filter(f, zip(a,b)).
• all() : give true if all the values in it is truth and TypeError is non iterable , no error
all(iterable)
• Returns True if all elements of the iterable are truthy.
• Returns False if any element is falsy.
• Works with any iterable: list, tuple, set, dict, etc.
nums = [1, 2, 3]
print(all(nums)) # True (all non-zero → truthy)
nums = [1, 0, 3]
print(all(nums)) # False (0 → falsy)flags = [True, True, False]
print(all(flags)) # Falsewords = ["hello", "world", ""]
print(all(words)) # False (empty string is falsy)print(all([])) # True → by definition, vacuously True• Iterates over keys by default:
d = {"a": 1, "b": 2, "c": 0}
print(all(d)) # True → keys are non-empty strings → truthy
print(all(d.values())) # False → one value is 0nums = [2, 4, 6, 8]
# check if all numbers are even
print(all(map(lambda x: x%2==0, nums))) # True
# filter then check
print(all(filter(lambda x: x>0, nums))) # True → all remaining >0• all() checks truthiness, not numeric comparison directly.
• Empty iterable → True.
• Works with any iterable.
• Often used in validation, conditions, or combined with map() / filter().
• any(iterable) : give true if any of value in iterable is true , TypeError if non iterable
any(iterable)
• Returns True if any element of the iterable is truthy.
• Returns False if all elements are falsy.
• Works with any iterable: list, tuple, set, dict, etc.
nums = [0, 0, 3]
print(any(nums)) # True (3 is truthy)
nums = [0, 0, 0]
print(any(nums)) # False (all falsy)flags = [False, False, True]
print(any(flags)) # Truewords = ["", "", "hello"]
print(any(words)) # True (non-empty string is truthy)
words = ["", ""]
print(any(words)) # Falseprint(any([])) # False → no truthy element• Iterates over keys by default:
d = {"a": 0, "b": 0, "c": 0}
print(any(d)) # True → keys are non-empty strings
print(any(d.values())) # False → all values are 0nums = [1, 3, 5, 8]
# check if any number is even
print(any(map(lambda x: x%2==0, nums))) # True (8 is even)
# filter then check
print(any(filter(lambda x: x>10, nums))) # False (all <=10)• any() checks truthiness, not numeric comparison directly.
• Empty iterable → False.
• Works with any iterable.
• Often used in validation, conditions, or combined with map() / filter().
• eval : it runs string as a python code
eval() takes a string that looks like a Python expression and runs it as if it were Python code, then returns the result.
Think of it like Python's interpreter reading a line of code dynamically at runtime.
x = 10
expr = "x + 5"
result = eval(expr)
print(result)What happens internally:
-
eval() receives the string "x + 5".
-
It parses the string to understand it's an expression: x + 5.
-
It evaluates it using the current environment (variables and functions accessible).
○ Here x is 10.
-
Computes the result: 10 + 5 = 15.
-
Returns 15.
So it's like writing:
result = x + 5… but the code comes from a string dynamically.
• Expression only: eval() can't execute statements like for, while, or print() alone.
eval("for i in range(3): print(i)") # ❌ SyntaxError• Dynamic execution: You can build code as a string at runtime.
a = 2
b = 3
expr = f"{a}**{b}" # "2**3"
print(eval(expr)) # 8• Access to current environment: variables, functions, etc.
user_input = "os.system('rm -rf /')"
eval(user_input) # ❌ Will execute dangerous code• This is why never use eval() on untrusted input.
Use ast.literal_eval() for parsing strings containing literals only:
import ast
s = "[1, 2, 3]"
lst = ast.literal_eval(s) # Safe
print(lst) # [1, 2, 3]• Works with strings, numbers, lists, dicts, tuples, booleans, None.
• ❌ Cannot run expressions like x + 5 — only static data.
eval(expression, globals=None, locals=None)
• Evaluates a string as a Python expression and returns the result.
• Can optionally use globals and locals dictionaries to control the environment.
x = 10
expr = "x + 5"
result = eval(expr)
print(result) # 15expr = "2 + 3 * 4"
print(eval(expr)) # 14a = 5
b = 7
expr = "a * b"
print(eval(expr)) # 35def square(x):
return x**2
expr = "square(6)"
print(eval(expr)) # 36x = 10
expr = "x + y"
print(eval(expr, {"y":5}, {})) # 15 → only `y` is passed• Never use eval() on untrusted input — it can execute arbitrary code.
# Dangerous:
# eval("__import__('os').system('rm -rf /')") # ❌• Safe alternatives: ast.literal_eval() (only evaluates literals like numbers, strings, lists, dicts).
import ast
s = "[1,2,3]"
lst = ast.literal_eval(s)
print(lst) # [1, 2, 3]• Returns the result of evaluated expression.
• Only works for single expressions, not statements like loops or if.
• Can pass globals / locals for controlled execution.
• Dangerous with untrusted input — use ast.literal_eval() if possible
lst = [1, 2]
lst.append([3,4])
print(lst) # [1, 2, [3, 4]]• Many expect it to "add elements individually," but it adds the list itself.
lst = [1,2]
lst.extend("abc")
print(lst) # [1, 2, 'a', 'b', 'c']• Strings, tuples, sets all work.
• But non-iterables raise TypeError:
lst.extend(5) # ❌ TypeErrorlst = [[1,2], [3,4]]
lst.append([5,6])
print(lst) # [[1,2],[3,4],[5,6]] → nested one level deeper
lst.extend([5,6])
print(lst) # [[1,2],[3,4],5,6] → elements added individually• append() → +1 length regardless of what you append.
lst = [1,2]
lst.append([3,4])
print(len(lst)) # 3• extend() → +len(iterable)
lst = [1,2]
lst.extend([3,4])
print(len(lst)) # 4lst = [1,2]
lst.extend({5,4})
print(lst) # [1,2,4,5] → order not guaranteed• Sets are iterables, but no order is preserved.
lst = []
lst.append([1,2])
lst[0].append(3)
print(lst) # [[1,2,3]] → changes inside the nested list reflect• Mutables are added by reference in append/extend.
lst = [1,2]
lst.append([3,4]).append(5) # ❌ AttributeError• append() and extend() return None, cannot chain.
lst = [1,2]
lst.extend([])
print(lst) # [1,2] → no change• append([]) would add an empty list → [1,2,[]]
lst = [1,2]
lst.append("abc") # [1,2,'abc']
lst.extend("abc") # [1,2,'abc','a','b','c']• If you expect characters to merge into the list, you need extend().
• Question: What's the difference between lst.append([1,2,3]) and lst.extend([1,2,3])?
• Answer: append → one element (the list) added; extend → each element added individually.
• People often forget this when the element is itself a list.
• append() → "add one object at the end"
• extend() → "unpack the iterable and add each element"
• Returns None → cannot chain
• Mutables are added by reference → modifying them later changes the list
• Strings are iterables → extend() breaks them into chars, append() adds whole string
• l.insert(item,index) : it inserts the element at the given specific index in the list , none error , it doesn't raise index out of range error if given index is less than zero it will add at first else at last , returns none modifies list in place
list.insert(index, element)
• Inserts an element at a specific position in the list.
• Shifts elements to the right to make space.
• Modifies the original list in place.
• Returns None.
lst = [1, 2, 3]
lst.insert(1, 10)
print(lst) # [1, 10, 2, 3]• index = 1 → insert before element at index 1.
lst = [1, 2, 3]
lst.insert(0, 100)
print(lst) # [100, 1, 2, 3]lst = [1, 2, 3]
lst.insert(len(lst), 200)
print(lst) # [1, 2, 3, 200]• ❌ Using append() is faster for end, but insert() works.
lst = [1, 2, 3]
lst.insert(-1, 99)
print(lst) # [1, 2, 99, 3]• Negative index counts from the end.
• If index < -len(lst) → inserts at beginning.
• If index > len(lst) → inserts at end.
lst = [[1], [2]]
lst.insert(1, [0])
print(lst) # [[1], [0], [2]]
lst[1].append(5)
print(lst) # [[1], [0,5], [2]] → mutable referencelst = [1, 2]
lst.insert(1, [3, 4])
print(lst) # [1, [3,4], 2] → inserted as **single element**• ❌ If you want to add elements individually, use extend() instead.
• Empty list:
lst = []
lst.insert(0, 10)
print(lst) # [10]• Index out of bounds:
lst = [1, 2]
lst.insert(100, 99)
print(lst) # [1, 2, 99] → adds at **end**
lst.insert(-100, 0)
print(lst) # [0, 1, 2, 99] → adds at **start**-
insert() shifts elements to the right → slow for large lists.
-
Works with any object: number, string, list, tuple, dict, etc.
-
Returns None → cannot chain.
-
Negative indices start from the end, but indices beyond range are handled gracefully.
-
Do not confuse with append/extend: insert() can place element anywhere, not just end.
• append() → add at end
• extend() → add elements individually at end
• insert() → add anywhere by index
If you want, I can make a mega table comparing append(), extend(), and insert() with tricky cases & examples, so it's super easy to memorize.
Do you want me to make that table?
You said:
is it give index out of range error
ChatGPT said:
No — insert() does not raise IndexError for out-of-range indices. Python handles it gracefully:
lst = [1, 2, 3]
lst.insert(100, 99) # index > len(lst)
print(lst) # [1, 2, 3, 99] → added at endlst = [1, 2, 3]
lst.insert(-100, 0) # index < -len(lst)
print(lst) # [0, 1, 2, 3] → added at start• Python caps the index:
○ index > len(lst) → inserts at end
○ index < -len(lst) → inserts at start
• No IndexError is raised, unlike direct assignment (lst[100] = 5 would fail).
• l.remove(element) : it will remove the first occurrence of element , returns none, Value Error if not found , removing from empty list also give value error
list.remove(element)
• Removes the first occurrence of the specified element from the list.
• Modifies the list in place.
• Returns None.
lst = [1, 2, 3, 2]
lst.remove(2)
print(lst) # [1, 3, 2] → removes **first 2 only**lst = [1, 2, 3]
lst.remove(5) # ❌ ValueError: list.remove(x): x not in list• Tip: check if element exists first:
if 5 in lst:
lst.remove(5)lst = ["a", "b", "c", "b"]
lst.remove("b")
print(lst) # ['a', 'c', 'b'] → removes **first occurrence**• Works with numbers, strings, tuples, objects, etc.
lst = [1, 2, 2, 2, 3]
lst.remove(2)
print(lst) # [1, 2, 2, 3] → only first 2 removed• To remove all occurrences → use a loop or list comprehension:
lst = [1, 2, 2, 3]
lst = [x for x in lst if x != 2]
print(lst) # [1, 3]lst = [[1], [2], [1]]
lst.remove([1])
print(lst) # [[2], [1]] → removes **first matching list**• Matches by equality (==), not by reference (is)
a = [1]
b = [1]
lst = [a, b]
lst.remove([1]) # removes a (first one) → equality usedlst = []
lst.remove(1) # ❌ ValueErrorlst = [1, 2, 3]
result = lst.remove(2)
print(result) # None → in-place operation• Cannot chain remove() calls.
-
Only first occurrence is removed.
-
Raises ValueError if element doesn't exist.
-
Works on mutable and immutable objects.
-
Cannot remove by index — that's what pop() is for.
• remove(x) → remove first x in list
• Not found → ValueError
• Only first → use list comprehension to remove all
• Returns None → cannot chain
• l.pop() : by default it remove the last element , if index is passed it will remove the element at that index, returns the deleted element , IndexError if index is > len(a) and if the list is empty
list.pop(index=-1)
• Removes and returns an element at the given index.
• Default index = -1 → removes the last element.
• Modifies the list in place.
lst = [1, 2, 3]
x = lst.pop()
print(x) # 3 → popped element
print(lst) # [1, 2]lst = [10, 20, 30]
y = lst.pop(1)
print(y) # 20
print(lst) # [10, 30]lst = [1, 2, 3]
x = lst.pop(-2)
print(x) # 2
print(lst) # [1, 3]• Works like normal list indexing.
lst = []
lst.pop() # ❌ IndexError: pop from empty list• Cannot pop if list is empty.
• pop() returns the removed element (unlike remove() which returns None).
lst = [1,2,3]
removed = lst.pop()
print(removed) # 3• Useful in stack (LIFO) operations.
stack = [1,2,3,4]
while stack:
print(stack.pop())
# Output: 4 3 2 1 → last-in-first-out| Feature | pop() | remove() |
|---------|-----------|--------------|
| Removes | by index | by value |
| Returns | removed element | None |
| Default | last element (-1) | must specify value |
| Raises error | IndexError if invalid | ValueError if not found |
-
pop() returns the removed element, unlike remove() (returns None).
-
Negative index works the same as normal indexing.
-
Default behavior pops last element → useful for stacks.
-
Index out of range → IndexError, cannot handle gracefully.
-
Can be used in LIFO operations.
-
Does not remove all occurrences → use remove() for that.
l.clear() : it will wmpty the list , outpot none, error none ,
🔹 Python List Method: clear()
✅ Definition
list.clear()
Removes all elements from the list.
Modifies the list in place.
Returns None.
- Basic Usage
lst = [1, 2, 3]
lst.clear()
print(lst) # []The list becomes empty, but the list object still exists.
- Return Value
lst = [1, 2, 3]
res = lst.clear()
print(res) # NoneImportant: clear() does not return the cleared list — it modifies in place.
- On Empty List
lst = []
lst.clear()
print(lst) # [] → no errorWorks safely even if the list is already empty.
- Effect on References
lst1 = [1, 2, 3]
lst2 = lst1 # another reference
lst1.clear()
print(lst2) # [] → also cleared!Tricky point: clear() affects all references to the list because it modifies the original object in place.
- Difference from Reassignment
lst1 = [1,2,3]
lst2 = lst1
lst1 = [] # reassigns lst1, lst2 unchanged
lst1.clear() # clears lst1 in place, lst2 also affectedlst = [] → creates a new list object
lst.clear() → empties existing list object
- Tricky / Interview Points
Returns None → cannot chain: lst.clear().append(1) ❌
Works with any list — empty or filled.
Modifies in place → references to the list are affected.
Cannot use with non-list objects → dict.clear(), set.clear() exist separately.
💡 TL;DR Memory Tricks
lst.clear() → empty the list in place
Existing references → also empty
Safe on empty list, returns None
l.index(value, start , end ) : it will give the index of first occurance of value , if not found ValueError, output is int
🔹 Python List Method: index()
✅ Definition
list.index(element, start=0, end=len(list))
Returns the index of the first occurrence of the element in the list.
Optional start and end arguments restrict the search to a subsection of the list.
Raises ValueError if the element is not found.
- Basic Usage
lst = [10, 20, 30, 20]
print(lst.index(20)) # 1 → first occurrence- Using start and end
lst = [10, 20, 30, 20, 40]
print(lst.index(20, 2)) # 3 → start searching from index 2
print(lst.index(20, 0, 2)) # 1 → search in index 0 to 1start is inclusive, end is exclusive.
- Element not in list → ❌ ValueError
lst = [1,2,3]
lst.index(5) # ❌ ValueError: 5 is not in listTip: use if x in lst before calling index() to avoid errors.
- Works with any object
lst = ["a", "b", "c", "b"]
print(lst.index("b")) # 1 → first occurrenceWorks with numbers, strings, tuples, objects, etc.
- Tricky Points
First occurrence only
lst = [1,2,3,2]
lst.index(2) # 1 → not 3IndexError confusion → People often think it raises IndexError if not found, but it’s ValueError.
Slicing with start/end
start and end are indices relative to the full list, not the sliced list.
Mutable objects
lst = [[1,2], [3,4], [1,2]]
print(lst.index([1,2])) # 0 → equality used, not reference- Quick Tips / Tricky Scenarios
Check before calling:
if 5 in lst:
print(lst.index(5))With tuples or other objects:
lst = [(1,2), (3,4)]
print(lst.index((3,4))) # 1Cannot use negative indices for index() start/end in confusing ways; they are interpreted as usual Python indices (start from end).
💡 TL;DR Memory Tricks
lst.index(x) → first index of x
Optional start/end restricts search
Raises ValueError if not found
First occurrence only
Equality (==) used, not identity
l.count(value) : give how much time the value is present , Output int , Error none ,
🔹 Python List Method: count()
✅ Definition
list.count(element)
Returns the number of occurrences of the specified element in the list.
Does not modify the list.
Works with any object.
- Basic Usage
lst = [1, 2, 2, 3, 2]
print(lst.count(2)) # 3 → number of times 2 appears- Works with strings in a list
lst = ["a", "b", "a", "c"]
print(lst.count("a")) # 2- Works with mutable objects
lst = [[1], [2], [1]]
print(lst.count([1])) # 2 → equality (`==`) is usedTricky point: count() uses equality comparison, not object identity.
- Element not present
lst = [1,2,3]
print(lst.count(5)) # 0 → returns 0, no errorUnlike index() or remove(), does not raise an error if element is absent.
- Nested lists / complex objects
lst = [[1,2], [3,4], [1,2]]
print(lst.count([1,2])) # 2 → matches equal listsWorks similarly for tuples, strings, or other objects.
- Tricky / important points
Does not modify the list → safe for checks.
Equality comparison used, not reference.
Returns 0 if element not found.
Works with any object type, including numbers, strings, tuples, lists, etc.
Can be used in conditionals:
if lst.count(2) > 1:
print("2 occurs more than once")💡 TL;DR Memory Tricks
lst.count(x) → how many times x appears
Equality (==) used, not identity
Returns 0 if not found
Does not modify the list
l.sort() : modifies the original list , TypeError if of mixed datatypes, output none , can use key , can use reverse to make dec to asc
🔹 Python list.sort() — Important & Expected Points
- Sorts the list in place
lst = [3, 1, 2]
lst.sort()
print(lst) # [1, 2, 3]✅ Important: modifies the original list, does not return a new list.
- Default behavior
Sorts in ascending order for numbers or lexicographically for strings.
lst = ["banana", "apple", "cherry"]
lst.sort()
print(lst) # ['apple', 'banana', 'cherry']- Using reverse=True
lst = [3, 1, 2]
lst.sort(reverse=True)
print(lst) # [3, 2, 1]Sorts in descending order.
- Using key argument
Provides a function that computes a value to sort by.
words = ["apple", "banana", "cherry"]
words.sort(key=len)
print(words) # ['apple', 'cherry', 'banana'] → sorted by length- Sorting by last character
words = ["dog", "cat", "elephant"]
words.sort(key=lambda x: x[-1])
print(words) # ['elephant', 'dog', 'cat']✅ Subtle point: when keys are equal, Python preserves original order (stable sort).
- Sorting lists of tuples/dicts
data = [("Alice", 25), ("Bob", 20)]
data.sort(key=lambda x: x[1]) # sort by age
print(data) # [('Bob', 20), ('Alice', 25)]Works for lists of any objects, as long as the key function returns a comparable value.
- Mixed types
lst = [1, "a", 2]
lst.sort() # ❌ TypeError: '<' not supported between instances of 'str' and 'int'Cannot sort a list with incompatible types without a custom key function.
- Stable sorting
Python’s sort is stable → preserves the relative order of elements with equal keys.
lst = [(1, 'b'), (2, 'a'), (1, 'a')]
lst.sort(key=lambda x: x[0])
print(lst) # [(1,'b'), (1,'a'), (2,'a')]✅ Important for multi-level sorting.
- Tricky / subtle points
Modifies the list in place, returns None → cannot chain calls.
key function is called once per element → efficient.
reverse=True does not reverse keys, only final order.
Works on numbers, strings, tuples, objects as long as elements are comparable.
Raises TypeError if elements are not comparable.
✅ TL;DR / Expected Uses
Sort a list in ascending or descending order.
Use key to sort by length, last character, dictionary values, object attributes.
Stable → preserves original order when keys are equal.
Use reverse=True for descending order.
Modifies the list in place → returns None.
l.reveerse() : it reverses the lsit , output nonr , s=reverse in place , none Error
🔹 Python list.reverse() — Important & Expected Points
- Reverses the list in place
lst = [1, 2, 3]
lst.reverse()
print(lst) # [3, 2, 1]✅ Important: modifies the original list, does not return a new list.
- Return value
lst = [1, 2, 3]
res = lst.reverse()
print(res) # NoneTricky point: returns None, so cannot chain calls.
- Works with any type
lst = ["a", "b", "c"]
lst.reverse()
print(lst) # ['c', 'b', 'a']Works with numbers, strings, tuples, objects — just reverses the order.
- Difference from slicing
lst = [1, 2, 3]
rev = lst[::-1]
print(rev) # [3, 2, 1] → new list
print(lst) # [1, 2, 3] → original list unchangedreverse() → in-place, no new list.
[::-1] → returns a new reversed list, original unchanged.
- Reversing after sorting
lst = [3, 1, 2]
lst.sort()
lst.reverse()
print(lst) # [3, 2, 1]✅ Expected use: combine with sort() for descending order.
- Empty list
lst = []
lst.reverse()
print(lst) # [] → safe, no error- Tricky / subtle points
- Modifies the list in place → all references to the list see the change.
- Returns None → cannot chain.
- Works for any object type.
- Safe on empty lists.
- Often used after sorting, or to implement stack reversal.
✅ TL;DR / Expected Uses
- Reverse the order of elements in a list in place.
- Works with numbers, strings, tuples, lists, or objects.
- Use after sorting to get descending order.
- Returns None, modifies original list.
- Safe for empty lists.
l.copy() : it give a list , creates the copy of list , error none
🔹 Python list.copy() — Important & Expected Points
- Creates a shallow copy of the list
lst = [1, 2, 3]
lst_copy = lst.copy()
print(lst_copy) # [1, 2, 3]✅ Important: new list object, but elements are the same references (shallow copy).
- Original list unaffected
lst = [1, 2, 3]
lst_copy = lst.copy()
lst_copy.append(4)
print(lst) # [1, 2, 3]
print(lst_copy) # [1, 2, 3, 4]Changes to the copy do not affect the original list.
- Shallow copy behavior with mutable elements
lst = [[1,2], [3,4]]
lst_copy = lst.copy()
lst_copy[0].append(5)
print(lst) # [[1,2,5], [3,4]] → inner list modified
print(lst_copy) # [[1,2,5], [3,4]]✅ Subtle point: copy() is shallow, so inner mutable objects are shared. For a deep copy, use copy.deepcopy() from the copy module.
- Works on empty list
lst = []
lst_copy = lst.copy()
print(lst_copy) # []Safe even if the list is empty.
- Return value
lst = [1, 2, 3]
res = lst.copy()
print(res) # [1, 2, 3] → returns the new listUnlike append(), extend(), or reverse(), copy() returns a new list.
- Tricky / subtle points
- Shallow copy → inner mutable elements are still shared.
- Modifies nothing, just returns a new list.
- Useful for preserving the original list before modifications.
- Can be combined with operations like sort() or reverse() without affecting the original list.
- Safer than slicing (lst[:]) when you want explicit copy semantics.
✅ TL;DR / Expected Uses
- Create a shallow copy of a list.
- Changes to the copy do not affect the original list (except inner mutables).
- Safe for empty lists.
- Returns new list object.
- Use when you want to preserve the original list before modifying it.