Python Course Notes – Strings & Lists
Python Course Notes
Strings & Lists – In-Depth Reference
Comprehensive notes with detailed explanations and coding examples
Table of Contents
PART 1: STRINGS
1.1 Introduction to Strings
1.2 Working with Strings
1.3 String Literals
1.4 Indexes and Slices
1.5 in and not in Operators
1.6 F-Strings
1.7 Useful String Methods
PART 2: LISTS
2.1 Introduction to Lists
2.2 List Indexes
2.3 Negative Indexes
2.4 Slices
2.5 len() Function
2.6 Updating Values
2.7 Concatenation and Replication
2.8 del Statement
2.9 Working with Lists
2.10 for Loops and Lists
2.11 in and not in with Lists
2.12 Multiple Assignment
2.13 List Methods
PART 3: QUICK REFERENCE TABLES
PART 1 — STRINGS
Strings are one of the most fundamental and frequently used data types in Python. Nearly every real-
world Python program uses strings extensively — for user input, file operations, web scraping, data
processing, and much more. Mastering strings is essential to becoming a proficient Python
programmer.
Page 1
Python Course Notes – Strings & Lists
1.1 Introduction to Strings
A string in Python is a sequence of characters. Characters can be letters, digits, symbols, spaces, or
even emojis. Strings are one of Python's built-in data types and belong to the category of sequence
types — which means every character in a string has a specific position (index).
Key Properties of Python Strings:
• Ordered: Characters maintain a specific left-to-right order.
• Immutable: Once created, a string cannot be modified. Any operation that appears to change a
string actually creates a new string.
• Iterable: You can loop through a string character by character.
• Indexed: Each character can be accessed via its position.
Example 1.1a – Creating and displaying strings
# A simple string
message = "Hello, World!"
print(message)
# String with single quotes
name = 'Alice'
print(name)
# String assigned to a variable
course = "Python Programming"
print(course)
# Checking the type
print(type(message)) # <class "str">
Hello, World!
Alice
Python Programming
<class 'str'>
Example 1.1b – Strings are immutable
s = "Hello"
# s[0] = "J" ← This would cause a TypeError!
# TypeError: "str" object does not support item assignment
# Correct way: create a new string
s = "J" + s[1:]
print(s) # "Jello"
"Jello"
💡 Because strings are immutable, Python can safely share and cache string objects, making them memory-
efficient.
1.2 Working with Strings
Python provides many ways to work with and manipulate strings. In this section we explore the basic
operations: concatenation, repetition, measuring length, and converting other types to strings.
Page 2
Python Course Notes – Strings & Lists
String Concatenation
Concatenation means joining two or more strings together using the + operator.
Example 1.2a – Concatenating strings
first_name = "John"
last_name = "Doe"
# Join with a space in between
full_name = first_name + " " + last_name
print(full_name) # "John Doe"
# Concatenate multiple strings
greeting = "Hello, " + first_name + "! How are you?"
print(greeting)
"John Doe"
"Hello, John! How are you?"
String Repetition
Use the * operator to repeat a string a number of times.
Example 1.2b – Repeating strings
separator = "-" * 30
print(separator) # prints 30 dashes
word = "ha"
laugh = word * 5
print(laugh) # "hahahahaha"
# Useful for formatting output
print("=" * 40)
print(" WELCOME TO PYTHON ")
print("=" * 40)
------------------------------
hahahahaha
========================================
WELCOME TO PYTHON
========================================
Measuring String Length – len()
The len() function returns the total number of characters in a string, including spaces and special
characters.
Example 1.2c – Using len()
city = "Bangalore"
print(len(city)) # 9
sentence = "Hello World"
print(len(sentence)) # 11 (space is counted!)
empty = ""
print(len(empty)) # 0
# Practical: check if password is long enough
password = "mypass123"
Page 3
Python Course Notes – Strings & Lists
if len(password) >= 8:
print("Password length OK")
else:
print("Password too short")
9
11
0
Password length OK
Converting Other Types to Strings – str()
Use str() to convert integers, floats, booleans, or other objects into strings.
Example 1.2d – Type conversion to string
age = 25
price = 99.95
active = True
# Convert to string
age_str = str(age)
price_str = str(price)
active_str= str(active)
print(type(age_str)) # <class "str">
print("Age: " + age_str) # "Age: 25"
# Without str() this would fail:
# print("Age: " + age) ← TypeError!
# Checking: int vs string "25"
print(25 == "25") # False (different types)
print(25 == int("25")) # True
<class 'str'>
"Age: 25"
False
True
💡 Always use str() when concatenating a number with a string, or use f-strings which handle the conversion
automatically.
1.3 String Literals
A string literal is a string value written directly in your source code. Python supports several forms of
string literals, each designed for different situations.
Single and Double Quotes
Both 'single quotes' and "double quotes" create strings. They are completely equivalent. The
main reason to choose one over the other is to avoid having to escape a quote character inside the
string.
Example 1.3a – Single vs double quotes
# Both are identical
s1 = 'Hello'
s2 = "Hello"
print(s1 == s2) # True
Page 4
Python Course Notes – Strings & Lists
# Use double quotes when string contains apostrophes
line1 = "It's a wonderful day" # needs escape
line2 = "It's a wonderful day" # no escape needed
print(line1)
# Use single quotes when string contains double quotes
line3 = 'She said "Hi"'
print(line3)
True
It's a wonderful day
She said "Hi"
Triple-Quoted Strings
Triple quotes (""" or ''') allow strings to span multiple lines. They also preserve newlines and internal
indentation.
Example 1.3b – Multi-line strings with triple quotes
poem = """
Roses are red,
Violets are blue,
Python is great,
And so are you!
"""
print(poem)
# Triple-quoted string for long messages
message = """Dear Student,
Welcome to the Python course.
We hope you enjoy learning!"""
print(message)
# Also used for multi-line docstrings
def greet(name):
"""
This function greets a person by name.
Parameters: name (str)
"""
return f"Hello, {name}!"
Escape Sequences
An escape sequence starts with a backslash \ and lets you include special characters inside a string.
Example 1.3c – Escape sequences
# Newline \n
print("Line 1\nLine 2\nLine 3")
# Tab \t
print("Name:\tAlice")
print("Score:\t95")
# Backslash \\
path = "C:\\Users\\Alice\\Documents"
print(path)
Page 5
Python Course Notes – Strings & Lists
# Quote inside string
print("He said \"Hello\"")
print('It\'s fine')
# Unicode character \u
print("\u2764 Python") # heart symbol
Line 1
Line 2
Line 3
Name: Alice
Score: 95
C:\Users\Alice\Documents
He said "Hello"
❤
It's fine
Python
Raw Strings
Prefix a string with r to create a raw string where backslashes are treated as literal characters, not
escape sequences. This is especially useful for file paths and regular expressions.
Example 1.3d – Raw strings
# Normal string: \n is interpreted as newline
print("Hello\nWorld") # prints on 2 lines
# Raw string: \n is kept as-is
print(r"Hello\nWorld") # prints: Hello\nWorld
# File paths on Windows
path = r"C:\Users\Alice\Desktop\[Link]"
print(path)
# Without raw string you must double every backslash
path2 = "C:\\Users\\Alice\\Desktop\\[Link]"
print(path == path2) # True
⚠️ Raw strings cannot end with an odd number of backslashes. r"path\" is a syntax error.
1.4 Indexes and Slices
Since a string is a sequence of characters, each character is assigned a numeric position called an
index. Python supports both positive (left-to-right) and negative (right-to-left) indexing.
Positive Indexing
Positive indexes start from 0 at the leftmost character and increase to the right.
Example 1.4a – Positive indexing
word = "Python"
# Characters: P y t h o n
# Index: 0 1 2 3 4 5
print(word[0]) # "P" first character
print(word[1]) # "y"
print(word[4]) # "o"
print(word[5]) # "n" last character
Page 6
Python Course Notes – Strings & Lists
# Accessing characters in a loop
for i in range(len(word)):
print(f"Index {i} -> {word[i]}")
"P"
"y"
"o"
"n"
Index 0 -> P
Index 1 -> y
Index 2 -> t
Index 3 -> h
Index 4 -> o
Index 5 -> n
Negative Indexing
Negative indexes count from the right. -1 is the last character, -2 is second-to-last, and so on.
Example 1.4b – Negative indexing
word = "Python"
# Characters: P y t h o n
# Neg Index: -6 -5 -4 -3 -2 -1
print(word[-1]) # "n" last character
print(word[-2]) # "o"
print(word[-6]) # "P" same as word[0]
# Useful: get last character without knowing length
text = "Hello, World!"
print(text[-1]) # "!"
"n"
"o"
"P"
"!"
⚠️ An IndexError is raised if you use an index that is out of range. For a string of length 6, valid indexes are
0–5 (or -1 to -6).
String Slicing
A slice extracts a portion (substring) of a string. The syntax is:
string[start : end : step]
• start – index where the slice begins (inclusive, default = 0)
• end – index where the slice stops (exclusive, default = end of string)
• step – how many characters to skip (default = 1)
Example 1.4c – Basic slicing
s = "Hello, World!"
# Index: 0123456789...
print(s[0:5]) # "Hello" (positions 0,1,2,3,4)
print(s[7:12]) # "World"
print(s[:5]) # "Hello" (omit start → from beginning)
Page 7
Python Course Notes – Strings & Lists
print(s[7:]) # "World!" (omit end → to end)
print(s[:]) # full copy of string
# Extract last 6 characters
print(s[-6:]) # "orld!"
# Extract every other character
print(s[::2]) # "Hlo ol!"
"Hello"
"World"
"Hello"
"World!"
"Hello, World!"
"orld!"
"Hlo ol!"
Example 1.4d – Step parameter and reversing
s = "abcdefghij"
# Step = 2: every 2nd character
print(s[::2]) # "acegi"
# Step = 3: every 3rd character
print(s[::3]) # "adgj"
# Negative step – read backwards
print(s[::-1]) # "jihgfedcba" (reversed)
# Reverse a word (common interview question!)
word = "Python"
reversed_word = word[::-1]
print(reversed_word) # "nohtyP"
# Check if a word is a palindrome
def is_palindrome(w):
return w == w[::-1]
print(is_palindrome("radar")) # True
print(is_palindrome("hello")) # False
"acegi"
"adgj"
"jihgfedcba"
"nohtyP"
True
False
💡
can.
Slices never raise an IndexError even if start or end is out of range — they simply return as much as they
1.5 in and not in Operators
The in and not in operators are membership operators. They check whether a substring exists
somewhere inside a string, returning True or False.
Basic Usage
Page 8
Python Course Notes – Strings & Lists
Example 1.5a – Checking substrings
sentence = "The quick brown fox jumps over the lazy dog"
# Check for a word
print("fox" in sentence) # True
print("cat" in sentence) # False
print("cat" not in sentence) # True
# Case-sensitive!
print("The" in sentence) # True
print("the" in sentence) # True (appears twice)
print("THE" in sentence) # False (uppercase not found)
True
False
True
True
True
False
Practical Uses
Example 1.5b – Practical in/not in usage
# Input validation
email = "alice@[Link]"
if "@" in email and "." in email:
print("Valid email format")
else:
print("Invalid email format")
# Checking for banned words
banned_words = ["spam", "advertisement", "click here"]
message = "This is not spam content"
for word in banned_words:
if word in message:
print(f"Warning: found banned word '{word}'")
break
# Check if string starts with a vowel
def starts_with_vowel(word):
return word[0].lower() in "aeiou"
print(starts_with_vowel("Apple")) # True
print(starts_with_vowel("Banana")) # False
# Check for digits
pin = "1234"
if all(c in "0123456789" for c in pin):
print("Valid PIN")
Valid email format
Warning: found banned word 'spam'
True
False
Valid PIN
⚠️ The in operator checks for a contiguous substring, not individual characters unless the substring is one
character long.
Page 9
Python Course Notes – Strings & Lists
1.6 F-Strings (Formatted String Literals)
F-strings, introduced in Python 3.6, are the modern and recommended way to embed variables and
expressions directly inside strings. They are faster, cleaner, and easier to read than older methods like
% formatting or .format().
Basic Syntax
Prefix the string with f (or F) and use {variable} or {expression} inside curly braces.
Example 1.6a – F-string basics
name = "Alice"
age = 25
city = "Bangalore"
# Old way ([Link])
msg1 = "Hello {}! You are {} years old.".format(name, age)
# F-string way (recommended)
msg2 = f"Hello {name}! You are {age} years old."
print(msg2)
# You can embed any expression
print(f"Next year you will be {age + 1}.")
print(f"Your name has {len(name)} characters.")
print(f"Name in uppercase: {[Link]()}")
print(f"You live in {city}.")
Hello Alice! You are 25 years old.
Next year you will be 26.
Your name has 5 characters.
Name in uppercase: ALICE
You live in Bangalore.
Number Formatting
F-strings support Python's format specification mini-language inside the curly braces using a colon:
{value:format_spec}
Example 1.6b – Formatting numbers
pi = 3.14159265358979
price = 1250.5
big = 1234567
# Decimal places
print(f"Pi = {pi:.2f}") # 2 decimal places
print(f"Pi = {pi:.5f}") # 5 decimal places
# Width and alignment
print(f"Price: {price:10.2f}") # width 10, 2 decimals
print(f"Pi: {pi:>10.3f}") # right-align in width 10
print(f"Pi: {pi:<10.3f}") # left-align in width 10
# Thousands separator
print(f"Population: {big:,}") # 1,234,567
# Percentage
score = 0.875
Page 10
Python Course Notes – Strings & Lists
print(f"Score: {score:.1%}") # 87.5%
# Binary, Octal, Hex
n = 255
print(f"Decimal: {n}") # 255
print(f"Binary: {n:b}") # 11111111
print(f"Octal: {n:o}") # 377
print(f"Hex: {n:x}") # ff
Pi = 3.14
Pi = 3.14159
Price: 1250.50
Pi: 3.142
Pi: 3.142
Population: 1,234,567
Score: 87.5%
Decimal: 255
Binary: 11111111
Octal: 377
Hex: ff
F-Strings with Expressions and Conditions
Example 1.6c – Expressions inside f-strings
# Mathematical expression
a, b = 12, 7
print(f"{a} + {b} = {a + b}")
print(f"{a} × {b} = {a * b}")
print(f"{a} ** 2 = {a ** 2}")
# Conditional expression (ternary)
score = 75
result = "Pass" if score >= 50 else "Fail"
print(result)
# Calling methods
items = ["apple", "banana", "cherry"]
print(", ".join(items))
print(f"Count: {len(items)}")
# Multi-line f-string
name = "Bob"
age = 30
status = "Adult" if age >= 18 else "Minor"
report = (
f"Name : {name}\n"
f"Age : {age}\n"
f"Status: {status}"
)
print(report)
12 + 7 = 19
12 × 7 = 84
12 ** 2 = 144
Score: 75 – Pass
Items: apple, banana, cherry
Count: 3
Name : Bob
Age : 30
Status: Adult
Page 11
Python Course Notes – Strings & Lists
💡 F-strings evaluate expressions at runtime. Keep them simple and readable — if the logic is complex,
compute it in a variable first, then use the variable in the f-string.
1.7 Useful String Methods
Python strings have a rich library of built-in methods. Because strings are immutable, all methods
return new strings rather than changing the original. Methods are called using dot notation:
[Link]().
Case Methods
Example 1.7a – Changing case
s = "Hello, World!"
print([Link]()) # "HELLO, WORLD!"
print([Link]()) # "hello, world!"
print([Link]()) # "Hello, World!" (each word capitalised)
print([Link]()) # "Hello, world!" (only first char)
print([Link]()) # "hELLO, wORLD!"
# Case-insensitive comparison
user_input = "YES"
if user_input.lower() == "yes":
print("User agreed")
"HELLO, WORLD!"
"hello, world!"
"Hello, World!"
"Hello, world!"
"hELLO, wORLD!"
User agreed
Stripping Methods
Example 1.7b – Removing whitespace and characters
# Whitespace stripping
s = " Hello, World! "
print(repr([Link]())) # "Hello, World!"
print(repr([Link]())) # "Hello, World! "
print(repr([Link]())) # " Hello, World!"
# Strip specific characters
url = "***important***"
print([Link]("*")) # "important"
text = "...Hello..."
print([Link](".")) # "Hello"
# Very useful for cleaning user input
user_name = " alice "
clean = user_name.strip()
print(f"User: [{clean}]")
"Hello, World!"
"Hello, World! "
" Hello, World!"
"important"
Page 12
Python Course Notes – Strings & Lists
"Hello"
"User: [alice]"
Searching Methods
Example 1.7c – Finding substrings
sentence = "the quick brown fox jumps over the lazy fox"
# find() – returns first index, or -1 if not found
print([Link]("fox")) # 16
print([Link]("cat")) # -1
# rfind() – searches from the RIGHT
print([Link]("fox")) # 40 (second "fox")
# index() – like find() but raises ValueError if not found
print([Link]("fox")) # 16
# [Link]("cat") ← ValueError
# count() – number of non-overlapping occurrences
print([Link]("fox")) # 2
print([Link]("the")) # 2
# startswith() and endswith()
filename = "report_2024.pdf"
print([Link]("report")) # True
print([Link](".pdf")) # True
print([Link](".docx")) # False
16
-1
40
16
2
2
True
True
False
Replacing and Splitting
Example 1.7d – replace() and split()
# replace(old, new) – replaces ALL occurrences
s = "I love cats. Cats are great. My cat is fluffy."
print([Link]("cat", "dog"))
print([Link]("cat", "dog", 2)) # replace only first 2
# split() – splits into a list
csv_line = "Alice,30,Engineer,Bangalore"
parts = csv_line.split(",")
print(parts)
sentence = "Hello World Python"
words = [Link]() # splits on whitespace by default
print(words)
# split with maxsplit
data = "a:b:c:d:e"
Page 13
Python Course Notes – Strings & Lists
print([Link](":", 2)) # ["a", "b", "c:d:e"]
# join() – opposite of split()
words = ["Python", "is", "awesome"]
print(" ".join(words)) # "Python is awesome"
print("-".join(words)) # "Python-is-awesome"
print("".join(words)) # "Pythonisawesome"
I love dogs. dogs are great. My dog is fluffy.
I love dogs. dogs are great. My cat is fluffy.
['Alice', '30', 'Engineer', 'Bangalore']
['Hello', 'World', 'Python']
['a', 'b', 'c:d:e']
Python is awesome
Python-is-awesome
Pythonisawesome
Checking Methods
Example 1.7e – is...() checking methods
# isdigit() – all characters are digits
print("123".isdigit()) # True
print("12.3".isdigit()) # False (dot is not a digit)
# isalpha() – all characters are letters
print("Hello".isalpha()) # True
print("Hello1".isalpha()) # False
# isalnum() – all letters or digits
print("Hello123".isalnum()) # True
print("Hello!".isalnum()) # False
# isspace() – only whitespace
print(" ".isspace()) # True
# isupper() / islower()
print("HELLO".isupper()) # True
print("hello".islower()) # True
print("Hello".isupper()) # False
# Practical: validate a PIN
pin = input("Enter PIN: ") # assume user enters "4821"
if [Link]() and len(pin) == 4:
print("Valid PIN")
else:
print("Invalid PIN")
True
False
True
False
True
False
True
True
True
False
Valid PIN
Page 14
Python Course Notes – Strings & Lists
Complete String Methods Reference Table
Method Description Example
upper() Convert to uppercase 'hello'.upper() → 'HELLO'
lower() Convert to lowercase 'HELLO'.lower() → 'hello'
title() Capitalise each word 'hi there'.title() → 'Hi
There'
capitalize() Capitalise first char only 'hello world'.capitalize()
→ 'Hello world'
swapcase() Swap upper/lower 'Hello'.swapcase() →
'hELLO'
strip() Remove leading/trailing whitespace ' hi '.strip() → 'hi'
lstrip() Remove leading whitespace ' hi'.lstrip() → 'hi'
rstrip() Remove trailing whitespace 'hi '.rstrip() → 'hi'
find(sub) First index of sub, -1 if missing 'abcabc'.find('b') → 1
rfind(sub) Last index of sub, -1 if missing 'abcabc'.rfind('b') → 4
index(sub) Like find(), raises ValueError if 'abc'.index('b') → 1
missing
count(sub) Non-overlapping occurrences 'banana'.count('a') → 3
replace(o,n) Replace old with new 'aab'.replace('a','x') →
'xxb'
split(sep) Split into list 'a,b'.split(',') →
['a','b']
join(iter) Join iterable into string ','.join(['a','b']) → 'a,b'
startswith(s) True if string starts with s 'Hello'.startswith('He') →
True
endswith(s) True if string ends with s 'Hello'.endswith('lo') →
True
isdigit() True if all chars are digits '123'.isdigit() → True
isalpha() True if all chars are letters 'abc'.isalpha() → True
isalnum() True if letters or digits only 'abc1'.isalnum() → True
isspace() True if all chars are whitespace ' '.isspace() → True
isupper() True if all chars are uppercase 'ABC'.isupper() → True
islower() True if all chars are lowercase 'abc'.islower() → True
center(w) Centre in field of width w 'hi'.center(6) → ' hi '
ljust(w) Left-justify in field of width w 'hi'.ljust(6) → 'hi '
rjust(w) Right-justify in field of width w 'hi'.rjust(6) → ' hi'
zfill(w) Pad with zeros on the left '42'.zfill(5) → '00042'
encode(enc) Encode string to bytes 'hi'.encode('utf-8') →
b'hi'
format(**kw) Format with named placeholders '{n}'.format(n='A') → 'A'
Page 15
Python Course Notes – Strings & Lists
PART 2 — LISTS
Lists are one of the most powerful and versatile data structures in Python. A list can hold an ordered
collection of items — numbers, strings, other lists, or any mix of types. Lists are mutable, meaning you
can change their contents after creation.
2.1 Introduction to Lists
A list is created by enclosing comma-separated values in square brackets []. Each item in the list is
called an element, and each element has a numeric index starting from 0.
Key Properties of Lists
• Ordered: Elements are stored in insertion order and that order is maintained.
• Mutable: You can add, remove, or change elements after creation.
• Heterogeneous: A single list can hold elements of different types.
• Dynamic: Lists grow and shrink automatically as needed.
• Nestable: Lists can contain other lists.
Example 2.1a – Creating various lists
# List of strings
fruits = ["apple", "banana", "cherry"]
# List of integers
numbers = [10, 20, 30, 40, 50]
# List of floats
temperatures = [36.5, 37.0, 38.2, 36.8]
# Mixed-type list
mixed = [1, "hello", 3.14, True, None]
# Empty list
empty = []
# Nested list (list of lists)
matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
print(fruits)
print(type(fruits)) # <class "list">
print(len(fruits)) # 3
['apple', 'banana', 'cherry']
<class 'list'>
3
2.2 Positive Indexes
Accessing elements of a list works exactly like accessing characters of a string. Each element has a
zero-based positive index from left to right.
Page 16
Python Course Notes – Strings & Lists
Example 2.2a – Positive index access
colors = ["red", "green", "blue", "yellow", "purple"]
# 0 1 2 3 4
print(colors[0]) # "red"
print(colors[1]) # "green"
print(colors[3]) # "yellow"
print(colors[4]) # "purple" (last element)
# Access elements of a nested list
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(matrix[0]) # [1, 2, 3] (first row)
print(matrix[1][2]) # 6 (row 1, column 2)
print(matrix[2][0]) # 7 (row 2, column 0)
"red"
"green"
"yellow"
"purple"
[1, 2, 3]
6
7
2.3 Negative Indexes
Negative indexes let you access elements from the end of the list without knowing its exact length. -1
is always the last element.
Example 2.3a – Negative index access
fruits = ["apple", "banana", "cherry", "date", "elderberry"]
# -5 -4 -3 -2 -1
print(fruits[-1]) # "elderberry" (last)
print(fruits[-2]) # "date"
print(fruits[-5]) # "apple" (same as fruits[0])
# Practical: get the last element dynamically
scores = [88, 72, 95, 61, 79]
print(f"Last score: {scores[-1]}") # 79
print(f"Second last: {scores[-2]}") # 61
# Negative index in a loop
for i in range(1, 4):
print(f"From end [{-i}]: {scores[-i]}")
"elderberry"
"date"
"apple"
Last score: 79
Second last: 61
From end [-1]: 79
From end [-2]: 61
From end [-3]: 95
2.4 Slices
List slices work identically to string slices: list[start:end:step]. A slice returns a new list (it does
not modify the original).
Example 2.4a – List slicing
Page 17
Python Course Notes – Strings & Lists
nums = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
print(nums[2:5]) # [20, 30, 40]
print(nums[:4]) # [0, 10, 20, 30]
print(nums[6:]) # [60, 70, 80, 90]
print(nums[::2]) # [0, 20, 40, 60, 80] (every 2nd)
print(nums[::-1]) # [90, 80, ..., 0] (reversed)
print(nums[1:8:3]) # [10, 40, 70] (step 3)
# Shallow copy of entire list
copy = nums[:]
copy[0] = 999
print(nums[0]) # 0 (original unchanged)
print(copy[0]) # 999
[20, 30, 40]
[0, 10, 20, 30]
[60, 70, 80, 90]
[0, 20, 40, 60, 80]
[90, 80, 70, 60, 50, 40, 30, 20, 10, 0]
[10, 40, 70]
0
999
Example 2.4b – Slice assignment (modifying part of a list)
letters = ["a", "b", "c", "d", "e"]
# Replace elements using slice
letters[1:3] = ["X", "Y"]
print(letters) # ["a", "X", "Y", "d", "e"]
# Delete elements using slice
letters[1:3] = []
print(letters) # ["a", "d", "e"]
# Insert elements (expand)
letters[1:1] = ["B", "C"]
print(letters) # ["a", "B", "C", "d", "e"]
["a", "X", "Y", "d", "e"]
["a", "d", "e"]
["a", "B", "C", "d", "e"]
2.5 The len() Function
The built-in len() function returns the number of elements in a list. This is commonly used with loops,
validation, and slicing.
Example 2.5a – Using len() with lists
fruits = ["apple", "banana", "cherry"]
print(len(fruits)) # 3
# Use len() to loop with index
for i in range(len(fruits)):
print(f"{i}: {fruits[i]}")
# Get last element safely
last = fruits[len(fruits) - 1]
print(last) # "cherry"
Page 18
Python Course Notes – Strings & Lists
# Empty list check
empty = []
if len(empty) == 0:
print("List is empty")
# Nested list
matrix = [[1,2,3],[4,5,6]]
print(len(matrix)) # 2 (number of rows)
print(len(matrix[0])) # 3 (number of columns)
3
0: apple
1: banana
2: cherry
"cherry"
List is empty
2
3
2.6 Updating Values in a List
Since lists are mutable, you can change any element by assigning to its index. You can also replace
multiple elements using slice assignment.
Example 2.6a – Modifying list elements
grades = [85, 72, 90, 65, 78]
print(grades) # original
# Update a single element
grades[1] = 80
print(grades) # [85, 80, 90, 65, 78]
# Update using negative index
grades[-1] = 82
print(grades) # [85, 80, 90, 65, 82]
# Update using slice (replace multiple at once)
grades[2:4] = [95, 70]
print(grades) # [85, 80, 95, 70, 82]
# Conditionally update
for i in range(len(grades)):
if grades[i] < 75:
grades[i] = 75 # no one gets below 75
print(grades)
[85, 72, 90, 65, 78]
[85, 80, 90, 65, 78]
[85, 80, 90, 65, 82]
[85, 80, 95, 70, 82]
[85, 80, 95, 75, 82]
2.7 Concatenation and Replication
Lists support the + operator for concatenation (joining) and the * operator for replication (repeating).
Example 2.7a – Concatenation and replication
# Concatenation with +
a = [1, 2, 3]
Page 19
Python Course Notes – Strings & Lists
b = [4, 5, 6]
c = a + b
print(c) # [1, 2, 3, 4, 5, 6]
# Augmented assignment +=
a += [4, 5]
print(a) # [1, 2, 3, 4, 5]
# Replication with *
zeros = [0] * 5
print(zeros) # [0, 0, 0, 0, 0]
pair = [1, 2] * 4
print(pair) # [1, 2, 1, 2, 1, 2, 1, 2]
# Practical: initialise a board
row = ["."] * 3
board = [row[:] for _ in range(3)] # 3x3 grid
board[1][1] = "X"
for r in board:
print(r)
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5]
[0, 0, 0, 0, 0]
[1, 2, 1, 2, 1, 2, 1, 2]
['.', '.', '.']
['.', 'X', '.']
['.', '.', '.']
⚠️ Do NOT do board = [row] * 3 when row is a list — all three rows would reference the same object. Use a
list comprehension with row[:] to create independent copies.
2.8 The del Statement
The del statement removes elements from a list by index or slice. Unlike remove() which searches by
value, del works by position.
Example 2.8a – Using del
animals = ["cat", "dog", "bird", "fish", "hamster"]
print(animals) # original
# Delete by index
del animals[2] # removes "bird"
print(animals)
# Delete by negative index
del animals[-1] # removes "hamster"
print(animals)
# Delete a slice
del animals[1:3] # removes "dog" and "fish"
print(animals)
# Delete entire variable
del animals
# print(animals) ← NameError: name "animals" is not defined
# Practical: remove all elements from list
nums = [1, 2, 3, 4, 5]
del nums[:] # clears list (same as [Link]())
Page 20
Python Course Notes – Strings & Lists
print(nums) # []
['cat', 'dog', 'bird', 'fish', 'hamster']
['cat', 'dog', 'fish', 'hamster']
['cat', 'dog', 'fish']
['cat']
[]
2.9 Working with Lists
Lists have many practical patterns you will use constantly. This section covers common operations:
checking emptiness, sorting, copying, searching, and nesting.
Checking if a List is Empty
Example 2.9a – Empty list checks
items = []
# Method 1: compare length to 0
if len(items) == 0:
print("List is empty")
# Method 2: Pythonic way (empty list is falsy)
if not items:
print("No items found")
# Non-empty list is truthy
data = [1, 2, 3]
if data:
print(f"Found {len(data)} items")
List is empty
No items found
Found 3 items
Sorting Lists
Example 2.9b – Sorting
nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]
# sort() modifies IN-PLACE, returns None
[Link]()
print(nums) # [1, 1, 2, 3, 3, 4, 5, 5, 6, 9]
# Descending order
[Link](reverse=True)
print(nums) # [9, 6, 5, 5, 4, 3, 3, 2, 1, 1]
# sorted() returns NEW list, original unchanged
original = [5, 2, 8, 1, 9]
new_sorted = sorted(original)
print(original) # [5, 2, 8, 1, 9] unchanged
print(new_sorted) # [1, 2, 5, 8, 9]
# Sort strings alphabetically
names = ["Charlie", "Alice", "Bob", "David"]
[Link]()
Page 21
Python Course Notes – Strings & Lists
print(names)
# Sort by length
words = ["banana", "fig", "apple", "kiwi"]
[Link](key=len)
print(words)
[1, 1, 2, 3, 3, 4, 5, 5, 6, 9]
[9, 6, 5, 5, 4, 3, 3, 2, 1, 1]
[5, 2, 8, 1, 9]
[1, 2, 5, 8, 9]
['Alice', 'Bob', 'Charlie', 'David']
['fig', 'kiwi', 'apple', 'banana']
Copying Lists
Example 2.9c – Copying lists correctly
original = [1, 2, 3, 4, 5]
# WRONG: assignment creates a reference, not a copy
alias = original
alias[0] = 999
print(original) # [999, 2, 3, 4, 5] ← original changed!
# CORRECT method 1: slice copy
original = [1, 2, 3, 4, 5]
copy1 = original[:]
copy1[0] = 999
print(original) # [1, 2, 3, 4, 5] ← unchanged
# CORRECT method 2: .copy() method
copy2 = [Link]()
# CORRECT method 3: list() constructor
copy3 = list(original)
print(copy2 == copy3) # True (same content)
[999, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
True
⚠️ Assignment (alias = original) does NOT copy a list — both variables point to the same object. Use slice
[:], .copy(), or list() to create an independent copy.
2.10 for Loops and Lists
The for loop is the standard and most Pythonic way to iterate over a list. Python provides several loop
patterns for different needs.
Basic for Loop
Example 2.10a – Simple iteration
fruits = ["apple", "banana", "cherry"]
# Iterate directly over elements
for fruit in fruits:
print(fruit)
Page 22
Python Course Notes – Strings & Lists
# Compute sum of a list
numbers = [10, 20, 30, 40, 50]
total = 0
for n in numbers:
total += n
print(f"Sum = {total}") # 150
# Find maximum manually
maximum = numbers[0]
for n in numbers:
if n > maximum:
maximum = n
print(f"Max = {maximum}") # 50
apple
banana
cherry
Sum = 150
Max = 50
Loop with Index – range(len())
Example 2.10b – Index-based loop
colors = ["red", "green", "blue"]
for i in range(len(colors)):
print(f"Index {i}: {colors[i]}")
# Useful when you need to modify elements
prices = [100, 200, 150, 300]
for i in range(len(prices)):
prices[i] = prices[i] * 0.9 # 10% discount
print(prices)
Index 0: red
Index 1: green
Index 2: blue
[90.0, 180.0, 135.0, 270.0]
enumerate() – Best of Both Worlds
Example 2.10c – Using enumerate()
students = ["Alice", "Bob", "Charlie", "Diana"]
# enumerate gives (index, value) pairs
for index, name in enumerate(students):
print(f"{index + 1}. {name}")
# Start index from 1 using start parameter
for rank, name in enumerate(students, start=1):
print(f"Rank {rank}: {name}")
1. Alice
2. Bob
3. Charlie
4. Diana
Rank 1: Alice
Rank 2: Bob
Page 23
Python Course Notes – Strings & Lists
Rank 3: Charlie
Rank 4: Diana
List Comprehensions
A list comprehension is a concise, Pythonic way to build a new list from an existing one in a single
line.
Example 2.10d – List comprehensions
# Syntax: [expression for item in iterable if condition]
# Squares of 1 to 10
squares = [x**2 for x in range(1, 11)]
print(squares)
# Even numbers only
evens = [x for x in range(1, 21) if x % 2 == 0]
print(evens)
# Convert all names to uppercase
names = ["alice", "bob", "charlie"]
upper_names = [[Link]() for name in names]
print(upper_names)
# Filter: only names longer than 3 chars
long_names = [name for name in names if len(name) > 3]
print(long_names)
# Extract numbers from a mixed list
mixed = [1, "a", 2, "b", 3, "c"]
nums_only = [x for x in mixed if isinstance(x, int)]
print(nums_only)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
['ALICE', 'BOB', 'CHARLIE']
['alice', 'charlie']
[1, 2, 3]
zip() – Iterate Over Multiple Lists
Example 2.10e – Using zip() with lists
names = ["Alice", "Bob", "Charlie"]
scores = [95, 87, 92]
grades = ["A", "B", "A"]
for name, score, grade in zip(names, scores, grades):
print(f"{name}: {score} ({grade})")
# Create a dict from two lists
mapping = dict(zip(names, scores))
print(mapping)
Alice: 95 (A)
Bob: 87 (B)
Charlie: 92 (A)
{'Alice': 95, 'Bob': 87, 'Charlie': 92}
Page 24
Python Course Notes – Strings & Lists
💡 Prefer enumerate() over range(len(list)) when you need both index and value. Use zip() when iterating
over multiple lists in parallel.
2.11 in and not in Operators with Lists
The in and not in operators check whether a value is present anywhere in a list. They perform a
linear search through the list.
Example 2.11a – Membership testing
fruits = ["apple", "banana", "cherry", "date"]
print("apple" in fruits) # True
print("mango" in fruits) # False
print("mango" not in fruits) # True
# Guard against index errors
search = "cherry"
if search in fruits:
idx = [Link](search)
print(f"Found {search} at index {idx}")
# Check numbers
primes = [2, 3, 5, 7, 11, 13, 17, 19]
for n in range(1, 15):
status = "prime" if n in primes else "not prime"
print(f"{n} is {status}")
True
False
True
Found cherry at index 2
1 is not prime
2 is prime
3 is prime
...
Example 2.11b – in with nested lists and conditions
# Nested list – checks for complete sub-list
matrix = [[1, 2], [3, 4], [5, 6]]
print([3, 4] in matrix) # True
print([1, 3] in matrix) # False
# Practical: allowed users check
allowed_users = ["admin", "alice", "bob"]
current_user = "alice"
if current_user in allowed_users:
print(f"Access granted to {current_user}")
else:
print("Access denied")
# Remove duplicates using in
numbers = [1, 2, 3, 2, 4, 1, 5, 3]
unique = []
for n in numbers:
if n not in unique:
[Link](n)
print(unique)
True
Page 25
Python Course Notes – Strings & Lists
False
Access granted to alice
[1, 2, 3, 4, 5]
2.12 Multiple Assignment (Unpacking)
Python lets you assign multiple list items to multiple variables in one statement. This is called
unpacking or destructuring.
Example 2.12a – Basic unpacking
# Unpack all elements
point = [10, 20]
x, y = point
print(f"x={x}, y={y}") # x=10, y=20
rgb = [255, 128, 0]
red, green, blue = rgb
print(f"R={red} G={green} B={blue}")
# Swap two variables elegantly
a, b = 100, 200
print(f"Before: a={a}, b={b}")
a, b = b, a
print(f"After: a={a}, b={b}")
x=10, y=20
R=255 G=128 B=0
Before: a=100, b=200
After: a=200, b=100
Example 2.12b – Extended unpacking with *
numbers = [1, 2, 3, 4, 5, 6, 7]
# Capture first, last, and middle with *
first, *middle, last = numbers
print(f"First: {first}") # 1
print(f"Middle: {middle}") # [2, 3, 4, 5, 6]
print(f"Last: {last}") # 7
# First and rest
head, *tail = numbers
print(f"Head: {head}") # 1
print(f"Tail: {tail}") # [2, 3, 4, 5, 6, 7]
# All but last
*init, last = numbers
print(f"Init: {init}") # [1, 2, 3, 4, 5, 6]
print(f"Last: {last}") # 7
# Unpack in a for loop
pairs = [[1, "one"], [2, "two"], [3, "three"]]
for num, word in pairs:
print(f"{num} = {word}")
First: 1
Middle: [2, 3, 4, 5, 6]
Last: 7
Head: 1
Tail: [2, 3, 4, 5, 6, 7]
Init: [1, 2, 3, 4, 5, 6]
Page 26
Python Course Notes – Strings & Lists
Last: 7
1 = one
2 = two
3 = three
⚠️ The number of variables must match the number of elements unless you use * (star/splat) for variable-
length unpacking.
2.13 List Methods
Python lists have a comprehensive set of built-in methods. Most modify the list in-place and return
None. Understanding each method thoroughly is essential for efficient Python programming.
append() – Add One Element to End
Example 2.13a – append()
fruits = ["apple", "banana"]
[Link]("cherry")
print(fruits) # ["apple", "banana", "cherry"]
[Link]("date")
[Link]("elderberry")
print(fruits)
# Building a list dynamically
squares = []
for i in range(1, 6):
[Link](i ** 2)
print(squares) # [1, 4, 9, 16, 25]
# Appending a list adds it as ONE element
lst = [1, 2, 3]
[Link]([4, 5])
print(lst) # [1, 2, 3, [4, 5]]
["apple", "banana", "cherry"]
["apple", "banana", "cherry", "date", "elderberry"]
[1, 4, 9, 16, 25]
[1, 2, 3, [4, 5]]
insert() – Add Element at Specific Position
Example 2.13b – insert()
colors = ["red", "green", "blue"]
# insert(index, value)
[Link](0, "black") # insert at beginning
print(colors) # ["black", "red", "green", "blue"]
[Link](2, "yellow") # insert at position 2
print(colors) # ["black", "red", "yellow", "green", "blue"]
# Insert at end (same as append)
[Link](len(colors), "white")
print(colors)
Page 27
Python Course Notes – Strings & Lists
# Insert at index beyond range → inserts at end
[Link](100, "pink")
print(colors[-1]) # "pink"
["black", "red", "green", "blue"]
["black", "red", "yellow", "green", "blue"]
extend() – Add All Elements of Iterable
Example 2.13c – extend()
a = [1, 2, 3]
b = [4, 5, 6]
# extend adds EACH element of b to a
[Link](b)
print(a) # [1, 2, 3, 4, 5, 6]
# Compare: append adds b as ONE element
x = [1, 2, 3]
[Link](b)
print(x) # [1, 2, 3, [4, 5, 6]]
# Extend from any iterable
lst = [1, 2]
[Link]("abc") # strings are iterable!
print(lst) # [1, 2, "a", "b", "c"]
[Link](range(3, 6))
print(lst)
[1, 2, 3, 4, 5, 6]
[1, 2, 3, [4, 5, 6]]
[1, 2, "a", "b", "c"]
[1, 2, "a", "b", "c", 3, 4, 5]
remove() – Remove by Value
Example 2.13d – remove()
animals = ["cat", "dog", "bird", "dog", "fish"]
# Removes FIRST occurrence only
[Link]("dog")
print(animals) # ["cat", "bird", "dog", "fish"]
# Remove all occurrences using a loop
while "dog" in animals:
[Link]("dog")
print(animals) # ["cat", "bird", "fish"]
# Safe removal: check before removing
if "cat" in animals:
[Link]("cat")
print("Removed cat")
# ValueError if element not found
# [Link]("elephant") ← ValueError!
["cat", "bird", "dog", "fish"]
["cat", "bird", "fish"]
Page 28
Python Course Notes – Strings & Lists
Removed cat
pop() – Remove and Return by Index
Example 2.13e – pop()
stack = [10, 20, 30, 40, 50]
# pop() with no argument removes LAST element
last = [Link]()
print(f"Popped: {last}") # 50
print(stack) # [10, 20, 30, 40]
# pop(index) removes at given index
first = [Link](0)
print(f"Popped: {first}") # 10
print(stack) # [20, 30, 40]
# STACK behaviour (LIFO) using pop()
stack2 = []
[Link]("a") # push
[Link]("b") # push
[Link]("c") # push
print([Link]()) # "c" ← last in, first out
print([Link]()) # "b"
Popped: 50
[10, 20, 30, 40]
Popped: 10
[20, 30, 40]
"c"
"b"
sort() and reverse()
Example 2.13f – sort() and reverse()
nums = [5, 2, 9, 1, 7, 3]
[Link]() # ascending in-place
print(nums) # [1, 2, 3, 5, 7, 9]
[Link](reverse=True) # descending
print(nums) # [9, 7, 5, 3, 2, 1]
# Sort strings
words = ["banana", "Apple", "cherry", "date"]
[Link]() # case-sensitive (uppercase first)
print(words)
[Link](key=[Link]) # case-insensitive
print(words)
# reverse() just flips the order (no sorting)
letters = ["d", "b", "c", "a"]
[Link]()
print(letters)
[1, 2, 3, 5, 7, 9]
[9, 7, 5, 3, 2, 1]
Page 29
Python Course Notes – Strings & Lists
['Apple', 'banana', 'cherry', 'date']
['Apple', 'banana', 'cherry', 'date']
['a', 'c', 'b', 'd']
index(), count(), clear(), copy()
Example 2.13g – More list methods
nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
# index() – find position of first occurrence
print([Link](5)) # 4
print([Link](5, 5)) # 8 (start searching from index 5)
# count() – count occurrences
print([Link](5)) # 3
print([Link](1)) # 2
print([Link](99)) # 0 (not found)
# clear() – remove all elements
temp = [1, 2, 3]
[Link]()
print(temp) # []
# copy() – shallow copy
original = [1, 2, 3]
duplicate = [Link]()
[Link](4)
print(original) # [1, 2, 3] unchanged
print(duplicate) # [1, 2, 3, 4]
4
8
3
2
0
[]
[1, 2, 3]
[1, 2, 3, 4]
Complete List Methods Reference Table
Method Description Example
append(x) Add x to the end [Link](4) → [1,2,3,4]
insert(i, x) Insert x at position i [Link](1,'a') →
[1,'a',2]
extend(iter) Add all items from iterable [Link]([4,5]) →
[1,2,3,4,5]
remove(x) Remove first occurrence of x [Link](2) → removes
first 2
pop(i=-1) Remove & return item at index i [Link]() → removes last
clear() Remove all items [Link]() → []
index(x[,s,e]) Index of first x (optional start/end) [5,3,5].index(5) → 0
count(x) Number of occurrences of x [1,2,1].count(1) → 2
Page 30
Python Course Notes – Strings & Lists
Method Description Example
sort(key,rev) Sort in-place [3,1,2].sort() → [1,2,3]
reverse() Reverse in-place [1,2,3].reverse() → [3,2,1]
copy() Return shallow copy new = [Link]()
PART 3 — QUICK REFERENCE
Use this section as a fast lookup guide when writing Python code.
String Quick Reference
• s = 'Hello' or s = "Hello" — create a string
• s[0] — first char; s[-1] — last char; s[i] — any char
• s[a:b] — substring from a to b-1; s[::-1] — reversed
• 'sub' in s — True if 'sub' appears in s
• f'Hello {name}' — embed variable in string
• [Link]() / [Link]() — case conversion
• [Link]() — remove whitespace; [Link](',') — split into list
• [Link]('a','b') — replace substrings; [Link]('x') — find position
• ','.join(lst) — join list into string
List Quick Reference
• lst = [1, 2, 3] — create a list
• lst[0] — first element; lst[-1] — last; lst[i] — any element
• lst[a:b] — sub-list; lst[::-1] — reversed copy
• len(lst) — number of elements
• lst[i] = x — update element; del lst[i] — delete element
• lst + lst2 — concatenate; lst * n — replicate
• x in lst — check membership
• a, b = lst — unpack; first, *rest = lst — extended unpack
• [Link](x) — add to end
• [Link](i, x) — insert at position
• [Link](lst2) — add multiple elements
• [Link](x) — remove by value
• [Link](i) — remove and return by index
• [Link]() — sort in-place; sorted(lst) — return sorted copy
• [Link]() — reverse in-place
• [Link](x) — find position of x
• [Link](x) — count occurrences
Page 31
Python Course Notes – Strings & Lists
• [Link]() — shallow copy
• [Link]() — remove all elements
Common Patterns
Read and clean user input
name = input("Enter name: ").strip().title()
print(f"Welcome, {name}!")
Count vowels in a string
def count_vowels(s):
return sum(1 for c in [Link]() if c in "aeiou")
print(count_vowels("Hello World")) # 3
Remove duplicates preserving order
def remove_duplicates(lst):
seen = []
return [x for x in lst if x not in seen and not [Link](x)]
print(remove_duplicates([1,2,3,2,1,4])) # [1,2,3,4]
Flatten a nested list
nested = [[1,2], [3,4], [5,6]]
flat = [x for sub in nested for x in sub]
print(flat) # [1, 2, 3, 4, 5, 6]
Group elements into chunks
def chunks(lst, n):
return [lst[i:i+n] for i in range(0, len(lst), n)]
print(chunks([1,2,3,4,5,6,7], 3)) # [[1,2,3],[4,5,6],[7]]
💡 Practice is the key to mastering Python. Try rewriting each example from memory, then experiment with
variations. The more you code, the more natural it becomes.
— End of Python Course Notes —
Page 32