# Python Comprehensive Revision Guide
## Table of Contents
1. [Python Basics](#basics)
2. [Python Intermediate Concepts](#intermediate)
3. [Python Advanced Topics](#advanced)
4. [Recent Python Features (3.11-3.12)](#recent)
5. [Coding Questions & Answers](#coding-questions)
6. [Best Practices & Interview Tips](#best-practices)
---
## BASICS
### 1. Variables & Data Types
**Definition:** Variables are containers for storing data. Python supports dynamic
typing, meaning you don't need to declare variable types explicitly.
**Purpose:** Variables allow you to store, modify, and retrieve data throughout
your program.
**Basic Syntax:**
```python
variable_name = value
```
**Supported Data Types:**
| Type | Definition | Example | Mutable |
|------ |----------- |------------------- |---------|
| **int** | Integer numbers | `x = 10` | - |
| **float** | Decimal numbers | `pi = 3.14` | - |
| **str** | Text/strings | `name = "Alice"` | - |
| **bool** | True/False values | `is_active = True` | - |
| **list** | Ordered, indexed collection | `[1, 2, 3]` | ✓ |
| **tuple** | Immutable ordered collection| `(1, 2, 3)` | ✗ |
| **dict** | Key-value pairs | `{'key': 'value'}` | ✓ |
| **set** | Unordered, unique items | `{1, 2, 3}` | ✓ |
**Sample Code:**
```python
# Basic variable assignment
age = 25
name = "John"
height = 5.9
is_student = False
# Type checking
print(type(age)) # <class 'int'>
# Type conversion (casting)
string_number = "42"
converted = int(string_number) # 42
```
---
### 2. Operators
**Definition:** Operators perform operations on variables and values.
**Categories:**
**Arithmetic Operators:**
```python
x = 10
y = 3
print(x + y) # 13 (Addition)
print(x - y) # 7 (Subtraction)
print(x * y) # 30 (Multiplication)
print(x / y) # 3.33... (Division)
print(x // y) # 3 (Floor Division)
print(x % y) # 1 (Modulus)
print(x ** y) # 1000 (Exponentiation)
```
**Comparison Operators:**
```python
5 == 5 # True (Equal)
5 != 3 # True (Not Equal)
5 > 3 # True (Greater than)
5 < 10 # True (Less than)
5 >= 5 # True (Greater than or equal)
5 <= 10 # True (Less than or equal)
```
**Logical Operators:**
```python
True and False # False
True or False # True
not True # False
```
**Assignment Operators:**
```python
x = 5 # Assignment
x += 3 # x = x + 3 (8)
x -= 2 # x = x - 2 (6)
x *= 2 # x = x * 2 (12)
x /= 3 # x = x / 3 (4.0)
```
**Membership Operators:**
```python
lst = [1, 2, 3]
2 in lst # True
4 not in lst # True
```
---
### 3. Control Flow Statements
**Definition:** Control flow statements direct the execution path of your program.
**If-Elif-Else:**
```python
age = 15
if age < 13:
print("Child")
elif age < 18:
print("Teenager")
else:
print("Adult")
```
**For Loops:**
```python
# Loop through list
for fruit in ["apple", "banana", "cherry"]:
print(fruit)
# Loop with range
for i in range(5): # 0, 1, 2, 3, 4
print(i)
# Loop with index
for i, fruit in enumerate(["apple", "banana"]):
print(f"{i}: {fruit}")
```
**While Loops:**
```python
count = 0
while count < 5:
print(count)
count += 1
```
**Break and Continue:**
```python
for i in range(10):
if i == 3:
continue # Skip iteration
if i == 7:
break # Exit loop
print(i)
```
```pass in Python:
pass is a null statement that does nothing and is used as a placeholder where a
statement is syntactically required.
Empty placeholder/Empty block
>To avoid syntax errors
>To write code structure first and implement later
```
---
### 4. String Methods & Formatting
**Definition:** Strings are sequences of characters. Python provides numerous
methods for manipulation.
**Common String Methods:**
```python
text = " Hello World "
print([Link]()) # " hello world "
print([Link]()) # " HELLO WORLD "
print([Link]()) # "Hello World" (remove whitespace)
print([Link]("World", "Python")) # " Hello Python "
print([Link]()) # ['Hello', 'World']
print("-".join(["a", "b", "c"])) # "a-b-c"
print([Link](" H")) # True
print([Link]("d ")) # True
print([Link]("World")) # 8
print([Link]("l")) # 3
```
**String Formatting:**
F-Strings (Python 3.6+) - Preferred:
```python
name = "Alice"
age = 30
price = 19.99
# Basic f-string
print(f"Name: {name}, Age: {age}") # Name: Alice, Age: 30
# Expressions in f-strings
print(f"Next year: {age + 1}") # Next year: 31
# Format specifiers
print(f"Price: ${price:.2f}") # Price: $19.99
print(f"Padded: {name:>10}") # Padded: Alice
```
.format() Method:
```python
print("Hello {}, you are {} years old".format(name, age))
print("Hello {name}, you are {age} years old".format(name="Alice", age=30))
```
---
### 5. Lists, Tuples, Dictionaries, and Sets
**Lists - Ordered, Mutable Collections:**
```python
fruits = ["apple", "banana", "cherry"]
# Accessing elements
print(fruits[0]) # "apple"
print(fruits[-1]) # "cherry" (last element)
# Slicing
print(fruits[1:3]) # ["banana", "cherry"]
print(fruits[:2]) # ["apple", "banana"]
print(fruits[::2]) # ["apple", "cherry"] (step of 2)
# Methods
[Link]("date")
[Link](1, "blueberry")
[Link]("banana")
[Link]() # Remove last item
length = len(fruits)
```
**Tuples - Immutable Collections:**
```python
coordinates = (10, 20, 30)
# Access like lists
print(coordinates[0]) # 10
# Cannot modify (immutable)
# coordinates[0] = 5 # TypeError
# Use when you need fixed data
person = ("John", 30, "Engineer")
name, age, job = person # Unpacking
```
**Dictionaries - Key-Value Pairs:**
```python
person = {
"name": "Alice",
"age": 30,
"city": "New York"
}
# Access values
print(person["name"]) # "Alice"
print([Link]("age")) # 30
print([Link]("email", "N/A")) # "N/A" (default if not found)
# Modification
person["age"] = 31
person["email"] = "alice@[Link]"
# Dictionary methods
[Link]("country", "USA") # Add if not exists
[Link]({"city": "Boston", "state": "MA"})
# Iteration
for key, value in [Link]():
print(f"{key}: {value}")
for key in [Link]():
print(key)
for value in [Link]():
print(value)
```
**Sets - Unique, Unordered Collections:**
```python
numbers = {1, 2, 3, 4, 5}
# Add/Remove
[Link](6)
[Link](3)
[Link](10) # No error if not found
# Set operations
set_a = {1, 2, 3}
set_b = {3, 4, 5}
print(set_a & set_b) # {3} (Intersection)
print(set_a | set_b) # {1, 2, 3, 4, 5} (Union)
print(set_a - set_b) # {1, 2} (Difference)
# Check membership
print(3 in numbers) # True
```
---
## INTERMEDIATE
### 6. Functions
**Definition:** Functions are reusable blocks of code that perform specific tasks.
**Basic Syntax:**
```python
def greet(name, greeting="Hello"):
"""
Docstring: Describes what the function does
"""
return f"{greeting}, {name}!"
print(greet("Alice")) # Hello, Alice!
print(greet("Bob", "Hi")) # Hi, Bob!
```
**Function Parameters:**
```python
# Default parameters
def introduce(name, age=25, city="Unknown"):
return f"{name}, {age}, from {city}"
# *args for variable positional arguments
def sum_numbers(*args):
return sum(args)
print(sum_numbers(1, 2, 3, 4, 5)) # 15
# **kwargs for variable keyword arguments
def print_info(**kwargs):
for key, value in [Link]():
print(f"{key}: {value}")
print_info(name="Alice", age=30, city="NYC")
# Combined
def full_example(a, b, *args, **kwargs):
print(f"a={a}, b={b}")
print(f"args={args}")
print(f"kwargs={kwargs}")
```
**Lambda Functions - Anonymous Functions:**
```python
# Single expression functions
square = lambda x: x ** 2
print(square(5)) # 25
# Often used with map, filter, sorted
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers)) # [1, 4, 9, 16, 25]
```
---
### 7. List Comprehensions & Generators
**List Comprehensions - Concise List Creation:**
```python
# Basic syntax: [expression for item in iterable if condition]
squares = [x ** 2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
evens = [x for x in range(10) if x % 2 == 0]
# [0, 2, 4, 6, 8]
# Nested comprehensions
matrix = [[i*j for j in range(3)] for i in range(3)]
# [[0, 0, 0], [0, 1, 2], [0, 2, 4]]
# Dictionary comprehension
squares_dict = {x: x**2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# Set comprehension
unique_squares = {x**2 for x in [1, 1, 2, 2, 3, 3]}
# {1, 4, 9}
```
**Generators - Memory-Efficient Iterators:**
```python
# Using yield to create generators
def count_up_to(n):
count = 1
while count <= n:
yield count
count += 1
counter = count_up_to(5)
print(next(counter)) # 1
print(next(counter)) # 2
# Loop through generator
for num in count_up_to(3):
print(num) # 1, 2, 3
# Generator expression
squares_gen = (x**2 for x in range(10))
print(next(squares_gen)) # 0
```
---
### 8. Object-Oriented Programming (OOP)
**Classes and Objects:**
```python
class Dog:
# Class variable (shared by all instances)
species = "Canine"
# Constructor
def __init__(self, name, age):
[Link] = name # Instance variable
[Link] = age
# Instance method
def bark(self):
return f"{[Link]} says Woof!"
# Special method (called when printing object)
def __str__(self):
return f"{[Link]} ({[Link]} years old)"
# Create object
dog = Dog("Buddy", 3)
print(dog) # Buddy (3 years old)
print([Link]()) # Buddy says Woof!
print([Link]) # Canine
```
**Inheritance - Classes inheriting from other classes:**
```python
class Animal:
def __init__(self, name):
[Link] = name
def speak(self):
return f"{[Link]} makes a sound"
class Cat(Animal): # Inherits from Animal
def speak(self): # Override method
return f"{[Link]} says Meow!"
cat = Cat("Whiskers")
print([Link]()) # Whiskers says Meow!
```
**Polymorphism:**
```python
def animal_sound(animal):
print([Link]())
dog = Dog("Rex")
cat = Cat("Fluffy")
animal_sound(dog) # Rex says Woof!
animal_sound(cat) # Fluffy says Meow!
```
**Encapsulation - Data Hiding:**
```python
class BankAccount:
def __init__(self, balance):
self.__balance = balance # Private attribute (name mangling)
def deposit(self, amount):
if amount > 0:
self.__balance += amount
def get_balance(self):
return self.__balance
account = BankAccount(1000)
[Link](500)
print(account.get_balance()) # 1500
# print(account.__balance) # Error: private attribute
```
---
### 9. Exception Handling
**Definition:** Handle errors gracefully to prevent program crashes.
**Try-Except-Finally:**
```python
try:
# Code that might raise an exception
num = int("abc")
except ValueError:
# Handle specific exception
print("Invalid number format")
except Exception as e:
# Handle any other exception
print(f"Error: {e}")
else:
# Executes if no exception occurred
print("Conversion successful")
finally:
# Always executes
print("Cleanup operations")
```
**Raising Exceptions:**
```python
def validate_age(age):
if age < 0:
raise ValueError("Age cannot be negative")
if age > 150:
raise ValueError("Age seems unrealistic")
return age
try:
validate_age(-5)
except ValueError as e:
print(f"Validation error: {e}")
```
**Custom Exceptions:**
```python
class InsufficientFundsError(Exception):
pass
def withdraw(balance, amount):
if amount > balance:
raise InsufficientFundsError(f"Attempted to withdraw {amount}, but balance
is {balance}")
return balance - amount
```
---
### 10. File Handling
**Definition:** Reading from and writing to files.
**Reading Files:**
```python
# Method 1: Using context manager (recommended)
with open('[Link]', 'r') as file:
content = [Link]() # Read entire file
# content = [Link]() # Read one line
# lines = [Link]() # Read all lines as list
# Method 2: Without context manager (not recommended)
file = open('[Link]', 'r')
content = [Link]()
[Link]()
```
**Writing Files:**
```python
# Write mode (overwrites existing content)
with open('[Link]', 'w') as file:
[Link]("Hello, World!")
# Append mode (adds to existing content)
with open('[Link]', 'a') as file:
[Link]("\nNew line")
# Write multiple lines
lines = ["Line 1\n", "Line 2\n", "Line 3\n"]
with open('[Link]', 'w') as file:
[Link](lines)
```
---
## ADVANCED
### 11. Decorators
**Definition:** Functions that modify or enhance other functions without
permanently changing them.
**Purpose:** Add functionality like logging, timing, authentication, caching.
**Simple Decorator:**
```python
def timing_decorator(func):
import time
def wrapper(*args, **kwargs):
start = [Link]()
result = func(*args, **kwargs)
end = [Link]()
print(f"Function took {end - start:.4f} seconds")
return result
return wrapper
@timing_decorator
def slow_function():
import time
[Link](1)
return "Done"
slow_function() # Shows execution time
```
**Decorator with Parameters:**
```python
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
results = []
for _ in range(times):
[Link](func(*args, **kwargs))
return results
return wrapper
return decorator
@repeat(3)
def greet(name):
return f"Hello, {name}!"
print(greet("Alice")) # ["Hello, Alice!", "Hello, Alice!", "Hello, Alice!"]
```
---
### 12. Async/Await & Concurrency
**Definition:** Asynchronous programming for handling I/O-bound operations
concurrently.
**Basic Async Example:**
```python
import asyncio
async def fetch_data(url):
print(f"Fetching {url}")
await [Link](2) # Simulate I/O operation
return f"Data from {url}"
async def main():
# Run multiple coroutines concurrently
results = await [Link](
fetch_data("url1"),
fetch_data("url2"),
fetch_data("url3")
)
print(results)
# Run the async function
[Link](main())
```
**Async with Error Handling:**
```python
async def safe_operation():
try:
result = await fetch_data("url")
return result
except Exception as e:
print(f"Error: {e}")
```
---
### 13. Context Managers
**Definition:** Objects that manage resource allocation and cleanup.
**Using Context Managers:**
```python
# File handling with context manager
with open('[Link]', 'r') as file:
content = [Link]()
# File automatically closed here
# Custom context manager
from contextlib import contextmanager
@contextmanager
def database_connection():
db = "Connected to database"
print(f"Opening: {db}")
try:
yield db
finally:
print("Closing connection")
with database_connection() as db:
print(f"Using: {db}")
```
---
### 14. Type Hints & Type Checking
**Definition:** Optional annotations specifying expected data types.
**Purpose:** Improve code clarity, enable static type checking with mypy.
**Basic Type Hints:**
```python
from typing import List, Dict, Optional, Union
# Function with type hints
def greet(name: str) -> str:
return f"Hello, {name}!"
# Variables with type hints
age: int = 30
is_active: bool = True
numbers: List[int] = [1, 2, 3]
person: Dict[str, Union[str, int]] = {"name": "Alice", "age": 30}
# Optional (can be None)
def get_age(person: Dict[str, any]) -> Optional[int]:
return [Link]("age")
```
**Python 3.10+ Union Type:**
```python
def process(value: int | str) -> None:
print(value)
```
---
## RECENT
### 15. Python 3.12 & 3.11 New Features
**Python 3.12 - Type Parameter Syntax (PEP 695):**
```python
# New generic type alias syntax
type Point = tuple[float, float]
# Generic with type parameters
type MyList[T] = list[T]
# With constraints
type NumericType[T: (int, float)] = T
# These replace the older TypeVar syntax
```
**Python 3.11 - Exception Groups:**
```python
# Handle multiple exceptions at once
try:
# Code that might raise multiple exceptions
pass
except* ValueError as eg:
print(f"Multiple ValueErrors: {[Link]}")
except* TypeError as eg:
print(f"Multiple TypeErrors: {[Link]}")
```
**Python 3.11 - Self Type:**
```python
from typing import Self
class Builder:
def set_name(self, name: str) -> Self:
[Link] = name
return self
def set_age(self, age: int) -> Self:
[Link] = age
return self
# Method chaining works with proper type hints
builder = Builder().set_name("Alice").set_age(30)
```
**Python 3.11 - Better Error Messages:**
```python
# Python 3.11 provides exact error locations in tracebacks
# Example: Points exactly to the problematic part of an expression
```
---
## CODING QUESTIONS
### BASIC LEVEL
**Q1: Reverse a String**
```
Problem: Write a function to reverse a string without using built-in slicing.
Difficulty: Easy
Time Complexity: O(n)
Space Complexity: O(n)
```
Solution:
```python
# Method 1: Using slicing
def reverse_string(s):
return s[::-1]
# Method 2: Using a loop
def reverse_string_loop(s):
reversed_str = ""
for char in s:
reversed_str = char + reversed_str
return reversed_str
# Method 3: Using recursion
def reverse_string_recursive(s):
if len(s) == 0:
return ""
return reverse_string_recursive(s[1:]) + s[0]
# Test
print(reverse_string("Hello")) # "olleH"
```
---
**Q2: Check if String is Palindrome**
```
Problem: Check if a string is a palindrome (ignoring spaces and case).
Difficulty: Easy
Time Complexity: O(n)
Space Complexity: O(n)
```
Solution:
```python
def is_palindrome(s):
# Remove non-alphanumeric characters and convert to lowercase
clean = ''.join([Link]() for c in s if [Link]())
# Check if equal to its reverse
return clean == clean[::-1]
# Test
print(is_palindrome("A man, a plan, a canal: Panama")) # True
print(is_palindrome("race a car")) # False
```
---
**Q3: Find Maximum in List**
```
Problem: Find the maximum element without using max() function.
Difficulty: Easy
Time Complexity: O(n)
Space Complexity: O(1)
```
Solution:
```python
def find_max(lst):
if not lst:
return None
max_val = lst[0]
for num in lst[1:]:
if num > max_val:
max_val = num
return max_val
# One-liner with reduce
from functools import reduce
max_val = reduce(lambda a, b: a if a > b else b, lst)
# Test
print(find_max([3, 7, 2, 9, 1])) # 9
```
---
### INTERMEDIATE LEVEL
**Q4: Two Sum**
```
Problem: Given an array of integers and a target sum, find two numbers that add up
to the target.
Return indices of the two numbers.
Difficulty: Medium
Time Complexity: O(n)
Space Complexity: O(n)
```
Solution:
```python
def two_sum(nums, target):
seen = {}
for i, num in enumerate(nums):
complement = target - num
if complement in seen:
return [seen[complement], i]
seen[num] = i
return []
# Test
print(two_sum([2, 7, 11, 15], 9)) # [0, 1]
print(two_sum([3, 2, 4], 6)) # [1, 2]
```
---
**Q5: Merge Overlapping Intervals**
```
Problem: Merge overlapping intervals from a list of intervals.
Difficulty: Medium
Time Complexity: O(n log n) due to sorting
Space Complexity: O(1)
```
Solution:
```python
def merge_intervals(intervals):
if not intervals:
return []
# Sort intervals by start position
[Link]()
merged = [intervals[0]]
for start, end in intervals[1:]:
if start <= merged[-1][1]:
# Overlapping intervals, merge them
merged[-1] = (merged[-1][0], max(merged[-1][1], end))
else:
# Non-overlapping, add to result
[Link]((start, end))
return merged
# Test
print(merge_intervals([(1, 3), (2, 6), (8, 10), (15, 18)]))
# [(1, 6), (8, 10), (15, 18)]
```
---
**Q6: Longest Substring Without Repeating Characters**
```
Problem: Find the length of the longest substring without repeating characters.
Difficulty: Medium
Time Complexity: O(n)
Space Complexity: O(min(m, n)) where m is charset size
```
Solution:
```python
def length_of_longest_substring(s):
char_index = {}
max_length = 0
start = 0
for i, char in enumerate(s):
if char in char_index and char_index[char] >= start:
start = char_index[char] + 1
char_index[char] = i
max_length = max(max_length, i - start + 1)
return max_length
# Test
print(length_of_longest_substring("abcabcbb")) # 3 ("abc")
print(length_of_longest_substring("bbbbb")) # 1 ("b")
print(length_of_longest_substring("pwwkew")) # 3 ("wke")
```
---
### ADVANCED LEVEL
**Q7: LRU Cache**
```
Problem: Implement an LRU Cache with O(1) get and put operations.
Difficulty: Hard
Time Complexity: O(1) for both get and put
Space Complexity: O(capacity)
```
Solution:
```python
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity):
[Link] = OrderedDict()
[Link] = capacity
def get(self, key):
if key not in [Link]:
return -1
# Move to end (most recent)
[Link].move_to_end(key)
return [Link][key]
def put(self, key, value):
if key in [Link]:
[Link].move_to_end(key)
[Link][key] = value
# Remove least recently used (first item)
if len([Link]) > [Link]:
[Link](last=False)
# Test
cache = LRUCache(2)
[Link](1, 1)
[Link](2, 2)
print([Link](1)) # 1
[Link](3, 3) # Evicts key 2
print([Link](2)) # -1 (not found)
```
---
**Q8: Word Ladder**
```
Problem: Find the shortest transformation sequence from beginWord to endWord.
Each intermediate word must be in the wordList, and differ by one letter.
Difficulty: Hard
Time Complexity: O(n * l * 26) where n is number of words, l is word length
Space Complexity: O(n * l)
```
Solution:
```python
from collections import deque
def ladder_length(begin_word, end_word, word_list):
if end_word not in word_list:
return 0
word_list = set(word_list)
queue = deque([(begin_word, 1)])
word_list.discard(begin_word)
while queue:
word, length = [Link]()
# Try changing each letter
for i in range(len(word)):
for c in "abcdefghijklmnopqrstuvwxyz":
new_word = word[:i] + c + word[i+1:]
if new_word == end_word:
return length + 1
if new_word in word_list:
word_list.remove(new_word)
[Link]((new_word, length + 1))
return 0
# Test
print(ladder_length("hit", "cog", ["hot", "dot", "dog", "lot", "log", "cog"])) # 5
```
---
## BEST PRACTICES & INTERVIEW TIPS
### PEP 8 Style Guide
```python
# Use 4 spaces for indentation
if True:
print("Correct")
# Variable and function names should be lowercase with underscores
user_name = "Alice"
def calculate_total():
pass
# Constants in UPPERCASE
MAX_SIZE = 100
PI = 3.14159
# Docstrings for modules, classes, and functions
def greet(name):
"""
Greet a person with their name.
Args:
name (str): The person's name
Returns:
str: Greeting message
"""
return f"Hello, {name}!"
# Line length should not exceed 79 characters
# Use meaningful names that express intent
```
### Performance Optimization
```python
# 1. Use list comprehensions instead of loops
# Bad
squared = []
for x in range(10):
[Link](x ** 2)
# Good
squared = [x ** 2 for x in range(10)]
# 2. Use generators for large datasets
# Bad
big_list = [x for x in range(1000000)]
# Good
big_gen = (x for x in range(1000000))
# 3. Use built-in functions (they're optimized)
# Bad
total = 0
for x in numbers:
total += x
# Good
total = sum(numbers)
# 4. Use dictionary lookups instead of linear search
# Bad
if item in list_of_items: # O(n)
pass
# Good
if item in set_of_items: # O(1)
pass
```
### Interview Tips
1. **Clarify Requirements:** Ask questions before coding.
2. **Think Out Loud:** Explain your approach to the interviewer.
3. **Start Simple:** Solve the problem first, then optimize.
4. **Test Edge Cases:** Empty inputs, single elements, large inputs.
5. **Time/Space Tradeoffs:** Discuss complexity and alternatives.
6. **Clean Code:** Use meaningful variable names and add comments.
7. **Avoid Common Mistakes:** Off-by-one errors, null pointer exceptions.
---
## Summary
This comprehensive guide covers Python from basics to advanced topics, including
recent features from Python 3.11 and 3.12. Practice the coding questions, apply
best practices, and you'll be well-prepared for Python interviews and real-world
development!
**Key Takeaways:**
- Master fundamentals: variables, data types, control flow
- Understand OOP: classes, inheritance, polymorphism
- Learn advanced patterns: decorators, generators, async/await
- Write efficient, readable code following PEP 8
- Practice algorithm problems regularly
- Keep learning new features in recent Python versions