Python is widely used and regarded as the most beginner-friendly programming language. However, to truly master it, you need to go beyond the basics and solve intermediate and advance coding problems. Also, you need to learn how to use advanced data structures, functional programming, and object-oriented design.
In this article, you’ll find a list of 65 intermediate Python coding questions primarily focuses on loops, list, dictionary, sets, OOP, decorators, Generators (yield), , and strings, multi-threading, List/Dict comprehensions, and Lambda functions, File Handling, regular expression, Date and Time, other miscellaneous topics.
These coding problems will improve your logic and coding skills, helping you write cleaner code and prepare for Python interviews.
What to Expect in These Exercises
Each exercise is structured to help you understand not just the how, but the why behind the code. Every problem includes:
- Practice Problem: You’ll get a clear description of what code you need to write.
- Exercise Purpose: You’ll learn why this skill is useful in real-world software development.
- Given Input and Expected Output: You’ll see examples to help you check your logic.
- Pythonic Hints: You will get a suggestion to guide you if you are stuck. These hints may point to a built-in function, module, algorithm, or concept, and will help you break down the problem without giving away the answer.
- Detailed Explanation: After you solve the problem, you will see a step-by-step breakdown of how the solution works and which Python concepts are used.
- Use the Online Python Code Editor to try out your solutions.
Also, See Python Exercises: 20 topic-wise sets and 385+ coding questions to practice.
+ Table of Contents (65 Exercises)
Table of contents
- Exercise 1: List Comprehension Mastery
- Exercise 2: Dictionary Merging with Logic
- Exercise 3: Frequency Map with Counter
- Exercise 4: Anagram Checker
- Exercise 5: Flatten a Nested List
- Exercise 6: Reverse Each Word of a String
- Exercise 7: Palindrome Sentence
- Exercise 8: List Comprehension Filtering (Advanced)
- Exercise 9: Remove Duplicates (Preserving Order)
- Exercise 10: Circular Shift (Rotation)
- Exercise 11: Dictionary Merging (Value Grouping)
- Exercise 12: Inverted Index
- Exercise 13: Dictionary Sorting (Lambda)
- Exercise 14: Subset and Superset Validation
- Exercise 15: Set Symmetric Difference
- Exercise 16: Power Set Generation
- Exercise 17: Age Calculator (Exact)
- Exercise 18: Countdown Timer (Time Delta)
- Exercise 19: Business Days Calculator
- Exercise 20: Custom Iterator Class
- Exercise 21: Find Duplicates in O(n) Time
- Exercise 22: Singly Linked List Implementation
- Exercise 23: Stack Implementation (LIFO)
- Exercise 24: Queue Implementation (FIFO)
- Exercise 25: Recursive Binary Search
- Exercise 26: Lambda Sorting with Tuples
- Exercise 27: Map and Filter Combination
- Exercise 28: Custom @timer Decorator
- Exercise 29: Fibonacci Generator (Memory Efficiency)
- Exercise 30: Custom Context Manager ( with statement)
- Exercise 31: The Versatile *args and **kwargs
- Exercise 32: Zip and Enumerate Mapping
- Exercise 33: Memoization with lru_cache
- Exercise 34: Set Operations for Data Analysis
- Exercise 35: Inheritance and Method Overriding
- Exercise 36: Encapsulation (Private Attributes)
- Exercise 37: Property Decorators ( @property )
- Exercise 38: Class Methods vs. Static Methods
- Exercise 39: Magic Methods ( __str__ and __add__ )
- Exercise 40: Abstract Base Classes (ABC)
- Exercise 41: Multiple Inheritance and MRO
- Exercise 42: Composition over Inheritance
- Exercise 43: The Singleton Pattern
- Exercise 44: Data Classes ( @dataclass )
- Exercise 45: CSV Processor
- Exercise 46: JSON Parser and Nested Access
- Exercise 47: Regular Expressions (Email Extractor)
- Exercise 48: Robust Error Handling (Try/Except/Finally)
- Exercise 49: OS Module (File Searcher)
- Exercise 50: Multi-threading (Concurrency)
- Exercise 51: API Requests with Error Handling
- Exercise 52: Word Frequency Counter
- Exercise 53: Student Management System
- Exercise 54: Password Strength Checker
- Exercise 55: Number Guessing Game (Computer vs User)
- Exercise 56: File Word Count Tool
- Exercise 57: Prime Number Generator
- Exercise 58: Email Validation Program
- Exercise 59: File-Based To-Do List App
- Exercise 60: Random Password Generator
- Exercise 61: Pascal’s Triangle
- Exercise 62: Smart Property Decorators
- Exercise 63: Caesar Cipher Implementation
- Exercise 64: Hollow Triangle Pattern
- Exercise 65: Solid Diamond Pattern
Exercise 1: List Comprehension Mastery
Practice Problem: Write a single-line list comprehension that takes a list of strings, filters out strings shorter than 4 characters, and converts the remaining strings to uppercase.
Exercise Purpose: List comprehensions are a hallmark of Pythonic code. They allow you to replace verbose for loops and .append() calls with a readable, optimized single line. This exercise teaches you how to combine transformation (uppercase) and filtering (length check) in one expression.
Given Input: words = ["apple", "bat", "cherry", "dog", "elderberry"]
Expected Output: ['APPLE', 'CHERRY', 'ELDERBERRY']
+ Hint
The syntax for a list comprehension with a filter is [expression for item in iterable if condition].
+ Show Solution
Explanation of Solution:
for w in words: This iterates through each element in the original list.if len(w) >= 4: This acts as a gatekeeper, only allowing strings with 4 or more characters to pass to the expression phase.w.upper(): This is the transformation applied to every item that passes the filter. The result is a brand-new list, leaving the originalwordslist untouched.
Exercise 2: Dictionary Merging with Logic
Practice Problem: Write a function that merges two dictionaries. If a key exists in both dictionaries, sum their values. If a key exists in only one, include it as is.
Exercise Purpose: Real-world data often comes from multiple sources. Simply using dict.update() would overwrite duplicate keys. This exercise introduces you to efficient dictionary iteration and the dict.get(key, default) method, which is essential for avoiding KeyError.
Given Input: dict_a = {'a': 10, 'b': 20} dict_b = {'b': 5, 'c': 15}
Expected Output: Merged Dictionary: {'a': 10, 'b': 25, 'c': 15}
+ Hint
- Start with a copy of the first dictionary.
- Iterate through the second dictionary and use the
+=operator to add values to existing keys.
+ Show Solution
Explanation of Solution:
d1.copy(): It is best practice not to mutate input arguments. Copying ensures the originaldict_aremains unchanged.d2.items(): This allows us to loop through both keys and values of the second dictionary simultaneously.result.get(key, 0): This is the “safe” way to access a dictionary. If the key exists, it returns the value; otherwise, it returns 0, allowing for a clean mathematical addition without anif/elseblock.
Exercise 3: Frequency Map with Counter
Practice Problem: Create a function that takes a string and returns a count of how many times each character appears. Ignore spaces and make it case-insensitive.
Exercise Purpose: While you could build a frequency map with a standard loop, Python’s collections module offers a specialized tool called Counter. This exercise teaches you to leverage the Standard Library to write less code while increasing performance.
Given Input: text = "Python Programming"
Expected Output:
Character Frequency:
Counter({'p': 2, 'y': 1, 't': 1, 'h': 1, 'o': 2, 'n': 2, 'r': 2, 'a': 1, 'g': 2, 'm': 2, 'i': 1})
+ Hint
Use .lower() and .replace(" ", "") to clean the string before passing it to the Counter class.
+ Show Solution
Explanation of Solution:
from collections import Counter:Counteris a subclass of dictionary specifically designed for counting hashable objects.input_string.lower().replace(" ", ""): This pre-processing step ensures that “P” and “p” are counted as the same character and that whitespace doesn’t clutter the results.Counter(clean_text): The constructor takes an iterable (like a string or list) and instantly tallies the occurrences of every element.
Exercise 4: Anagram Checker
Practice Problem: Write a function that determines if two strings are anagrams (contain the exact same characters in a different order).
Exercise Purpose: This problem introduces the concept of algorithmic sorting as a comparison tool. It demonstrates that transforming data into a “canonical” or “standard” form (sorted) makes comparison trivial.
Given Input: word1 = "listen", word2 = "silent"
Expected Output: Is "listen" an anagram of "silent"? True
+ Hint
- If two strings are anagrams, their sorted versions will be identical strings.
- Sort both strings in alphabetical order.
+ Show Solution
Explanation of Solution:
sorted(str1...): Thesorted()function takes the characters of the string and returns them as a sorted list (e.g.,['e', 'i', 'l', 'n', 's', 't']).s1 == s2: In Python, you can compare two lists directly using==. It checks if they have the same elements in the same order.- Efficiency: Sorting takes O(n log n) time, which is very efficient for standard string comparisons.
Exercise 5: Flatten a Nested List
Practice Problem: Write a recursive function that takes a list containing other lists (of any depth) and returns a single “flat” list of all elements.
Exercise Purpose: Intermediate Python often involves dealing with nested data (like JSON). This exercise teaches Recursion—the ability of a function to call itself—to drill down into nested structures until it finds base values.
Given Input: nested = [1, [2, 3], [4, [5, 6]], 7]
Expected Output: Flattened: [1, 2, 3, 4, 5, 6, 7]
+ Hint
- Iterate through the list.
- If an item is a list, call the function again on that item.
- If it’s not, append it to your results.
+ Show Solution
Explanation of Solution:
isinstance(item, list): This checks if the current element is another container.flatten(item): This is the recursive call. The function pauses its current work to “dive” into the sub-list.extend()vsappend():appendadds an item as it is, whileextendtakes all elements from an iterable and adds them individually to the list. This is crucial for merging the results of the recursive calls.
Exercise 6: Reverse Each Word of a String
Practice Problem: Given a sentence, reverse each individual word within the string while maintaining the original word order.
Exercise Purpose: This exercise teaches you the difference between reversing a sequence (the whole string) and iterating through sub-sequences (words). It emphasizes the use of the .split() and .join() methods, which are essential for text processing.
Given Input: "Python is awesome"
Expected Output: "nohtyP si emosewa"
+ Hint
- Split the string into a list of words.
- Use slicing
[::-1]to reverse each word, and then join them back together with spaces.
+ Show Solution
Explanation of Solution:
sentence.split(): This breaks the string into a list:['Python', 'is', 'awesome'].word[::-1]: This is the Pythonic way to reverse a string. It starts at the end and steps backward to the beginning." ".join(...): This takes the list of reversed words and stitches them together with a space character between each.
Exercise 7: Palindrome Sentence
Practice Problem: Write a function to check if a full sentence is a palindrome. You must ignore case, spaces, and all punctuation marks.
Exercise Purpose: Real-world palindromes often include punctuation (e.g., “Madam, I’m Adam”). This exercise teaches you how to sanitize data using isalnum() (is alphanumeric) before performing logic, ensuring your algorithm only focuses on the relevant characters.
Given Input: "A man, a plan, a canal: Panama"
Expected Output: True
+ Hint
Use a generator expression or loop to build a new string containing only lowercase letters and numbers, then compare that string to its reverse.
+ Show Solution
Explanation of Solution:
char.isalnum(): This method returnsTrueonly if the character is a letter or a number, effectively stripping out commas, colons, and spaces.clean_str[::-1]: By comparing the sanitized string to its reversed version, we can instantly determine symmetry.- Case Sensitivity: Converting everything to
.lower()is vital, as'A'does not equal'a'in Python.
Exercise 8: List Comprehension Filtering (Advanced)
Practice Problem: Given a list of strings, use a single list comprehension to extract strings that meet two criteria: they must be longer than 5 characters AND they must start with a vowel (a, e, i, o, u).
Exercise Purpose: This exercise builds “filter stacking” skills. In professional Python development, you often need to perform complex data extraction in a readable, concise way without writing multiple if statements.
Given Input: ["apple", "education", "ice", "ocean", "python", "umbrella"]
Expected Output: ['education', 'umbrella']
+ Hint
Your condition in the list comprehension will use the and operator and should check s[0].lower() in 'aeiou'.
+ Show Solution
Explanation of Solution:
w[0].lower() in 'aeiou': This is a very efficient way to check for multiple possible characters. It checks the first letter of the word against the vowels string.- Short-circuiting: Using
andis efficient; iflen(w) > 5is False, Python won’t even bother checking if it starts with a vowel. - Readability: Even with two conditions, the list comprehension remains clear and declarative.
Exercise 9: Remove Duplicates (Preserving Order)
Practice Problem: Write a function that removes duplicate elements from a list. You cannot use set() because sets do not maintain the original order of elements.
Exercise Purpose: While list(set(items)) is the fastest way to get unique items, it scrambles the order. This exercise teaches you how to use an auxiliary “seen” collection to maintain sequence integrity, a common requirement in data logging.
Given Input: [1, 2, 2, 3, 1, 4, 2]
Expected Output: [1, 2, 3, 4]
+ Hint
Create an empty list for results and an empty set for “seen” items (for O(1) lookup speed). Loop through the input; if an item isn’t in “seen”, add it to both.
+ Show Solution
Explanation of Solution:
- Hybrid Approach: We use a
resultlist to keep the order and aseenset to make the “is this a duplicate?” check instant. - Efficiency: Using
if x not in resultwould work but would get slower as the list grows (O(n2)). Using a set makes this run in O(n) time. - Persistence: The first time an element appears, it is locked into its position in the
resultlist and marked inseen.
Exercise 10: Circular Shift (Rotation)
Practice Problem: Create a function rotate_list(lst, n, direction) that shifts the elements of a list by N positions. The direction can be ‘left’ or ‘right’.
Exercise Purpose: List rotation is common in cryptography and UI carousels. This exercise teaches you how to use slicing and the modulo operator to handle shifts that are larger than the list length.
Given Input: List: [1, 2, 3, 4, 5], Shift: 2, Direction: 'right'
Expected Output: [4, 5, 1, 2, 3]
+ Hint
Use slicing. For a right shift of n, the result is lst[-n:] + lst[:-n].
+ Show Solution
Explanation of Solution:
n = n % len(lst): This ensures that if you shift a 5-item list by 102, it acts like a shift of 2, preventing index errors.- Slicing Logic:
lst[-n:]captures the “tail” of the list that will wrap around to the front.lst[:-n]captures the “head” that gets pushed forward. +Operator: Python allows you to concatenate lists easily, making the “wrap around” effect look like simple addition.
Exercise 11: Dictionary Merging (Value Grouping)
Practice Problem: Merge two dictionaries. If they share a key, the new dictionary should store a list containing values from both dictionaries instead of overwriting the first one.
Exercise Purpose: Standard dictionary merging (dict.update()) overwrites data. This exercise teaches you how to “preserve” data during a merge, which is essential when combining user settings or merging search results from different sources.
Given Input: d1 = {"a": 1, "b": 2}, d2 = {"b": 3, "c": 4}
Expected Output: {'a': [1], 'b': [2, 3], 'c': [4]}
+ Hint
Iterate through the unique keys of both dictionaries (using a set of keys) and check if the key exists in one or both.
+ Show Solution
Explanation of Solution:
set(d1) | set(d2): The pipe|operator performs a Union of the keys, ensuring we don’t miss any keys and we don’t process duplicates.- List Values: By making every value a list (even if there is only one item), we maintain a consistent data structure that is easy to iterate over later.
Exercise 12: Inverted Index
Practice Problem: Create a function that “inverts” a dictionary. Convert a dictionary of Author: [List of Books] into a dictionary of Book: Author.
Exercise Purpose: This is the logic behind how search engines work! An Inverted Index allows you to search for a term (the book) and immediately find where it belongs (the author). It emphasizes the use of nested loops and dictionary assignment.
Given Input:
{"Orwell": ["1984", "Animal Farm"], "Huxley": ["Brave New World"]}Code language: Python (python)
Expected Output:
{'1984': 'Orwell', 'Animal Farm': 'Orwell', 'Brave New World': 'Huxley'}
+ Hint
- Loop through the items of the original dictionary.
- For every book in the author’s list, make the book a key in the new dictionary and assign the author as the value.
+ Show Solution
Explanation of Solution:
- Nested Iteration: The outer loop picks an author; the inner loop “unpacks” their list of books.
- Key Swap: We take what was a value (the book) and make it a key. This only works if books are unique across the dataset.
- Application: This logic is used to map tags to articles, ingredients to recipes, or users to groups.
Exercise 13: Dictionary Sorting (Lambda)
Practice Problem: Given a list of dictionaries (representing employees), sort them based on their “salary” in descending order using a lambda function.
Exercise Purpose: In data processing, you rarely sort simple lists of numbers. You almost always sort “objects” (dictionaries). This exercise teaches you how to use the key parameter in Python’s sort() to target specific fields within a complex structure.
Given Input:
employees = [{"name": "A", "salary": 50}, {"name": "B", "salary": 70}, {"name": "C", "salary": 60}]Code language: Python (python)
Expected Output:
[{'name': 'B', 'salary': 70}, {'name': 'C', 'salary': 60}, {'name': 'A', 'salary': 50}]
+ Hint
Use sorted(list, key=lambda x: x['key_name'], reverse=True).
+ Show Solution
Explanation of Solution:
- Lambda as a Proxy: The lambda
x: x['salary']tells Python: “When you compare two dictionaries, don’t look at the whole thing; just look at the ‘salary’ value.” reverse=True: This flag switches the sort from ascending (default) to descending.- Stability: Python’s
sorted()is stable, meaning if two employees had the same salary, their original order relative to each other would not change.
Exercise 14: Subset and Superset Validation
Practice Problem: Write a script that takes two lists of integers from a user, converts them to sets, and determines if the first set is a Subset, a Superset, or Disjoint from the second.
Exercise Purpose: This exercise introduces formal relational logic between collections. Understanding these relationships is vital when managing user permissions (is this set of permissions a subset of the required ones?) or validating categories.
Given Input: Set A: {1, 2, 3}, Set B: {1, 2, 3, 4, 5}
Expected Output: Set A is a subset of Set B.
+ Hint
Use the built-in methods .issubset(), .issuperset(), and .isdisjoint().
+ Show Solution
Explanation of Solution:
.issubset(): ReturnsTrueif every element of Set A is contained within Set B..issuperset(): ReturnsTrueif Set A contains every element of Set B (plus potentially more)..isdisjoint(): ReturnsTrueif the intersection of the two sets is empty. It’s a quick way to check for “zero overlap.”
Exercise 15: Set Symmetric Difference
Practice Problem: Given two lists of student IDs, find the IDs that appear in either the first or the second list, but not in both.
Exercise Purpose: This is known as the Symmetric Difference. It is a powerful way to identify “exclusive” data. For example, finding customers who visited either in January or February, but did not visit in both months.
Given Input: list1 = [101, 102, 103], list2 = [103, 104, 105]
Expected Output: {101, 102, 104, 105}
+ Hint
Use the ^ operator between two sets.
+ Show Solution
Explanation of Solution:
- The
^Operator: This finds elements that are in(Set A OR Set B)minus(Set A AND Set B). - Readability: Using the set operator is significantly cleaner than writing two separate loops with
if x not in listlogic. - Performance: Like all set operations in Python, this is executed in O(n) time, making it efficient for thousands of entries.
Exercise 16: Power Set Generation
Practice Problem: Write a function that generates the Power Set of a given set (a set of all possible subsets, including the empty set and the set itself).
Exercise Purpose: Generating power sets is a fundamental concept in Combinatorics and algorithm design (like solving the knapsack problem). This exercise introduces you to the itertools module, specifically combinations.
Given Input: [1, 2, 3]
Expected Output:
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
+ Hint
Use itertools.combinations in a loop that varies the size of the subset from 0 to the length of the list.
+ Show Solution
Explanation of Solution:
combinations(elements, r): This built-in function generates all possible ways to pickritems from the list without repetition and regardless of order.range(len(elements) + 1): We start at 0 to include the Empty Set()and go up to the full length to include the original set.- Growth: Keep in mind that the power set of a set with N elements has 2n subsets. For 3 elements, you get 8 subsets; for 10 elements, you get 1,024!
Exercise 17: Age Calculator (Exact)
Practice Problem: Create a function that asks for a user’s birthdate (YYYY-MM-DD) and calculates their exact age today in years, months, and days.
Exercise Purpose: Date math is notoriously difficult because of leap years and varying month lengths. This exercise teaches you to use the datetime and dateutil.relativedelta modules, which are the industry standards for handling temporal data in Python.
Given Input: Birthdate: 1995-05-15, Today: 2026-01-02
Expected Output: Age: 30 years, 7 months, 18 days
+ Hint
Use datetime.strptime to parse the input string and relativedelta to calculate the difference.
+ Show Solution
Explanation of Solution:
strptime: This function converts a string into adatetimeobject based on a format code (%Yfor 4-digit year, etc.).relativedelta: Unlike a standardtimedelta(which only tracks days and seconds),relativedeltaunderstands the calendar and can correctly calculate years and months while accounting for leap years.- Error Handling: The
try/exceptblock ensures that if a user types an impossible date (like “1995-02-30”), the program provides a helpful error instead of crashing.
Exercise 18: Countdown Timer (Time Delta)
Practice Problem: Write a function that calculates the exact number of days, hours, and minutes remaining until the upcoming New Year’s Day.
Exercise Purpose: This exercise teaches you how to perform arithmetic on time objects. Since time is not base-10, you cannot simply subtract numbers; you must use datetime objects and understand the “Timedelta” result to extract specific units.
Given Input: Current Date: 2026-01-02
Expected Output: 363 days, 16 hours, 50 minutes until New Year!
+ Hint
- Calculate the target date (Jan 1 of the next year) and subtract
datetime.now(). - Use integer division and the modulo operator (
%) to convert the remaining seconds into hours and minutes.
+ Show Solution
Explanation of Solution:
datetime(next_year, 1, 1): This creates a fixed point in the future to compare against.diff.days: The subtraction of two datetimes returns atimedeltaobject, which conveniently stores the total number of whole days.divmod(seconds, 3600): This is a Pythonic utility that returns both the quotient (hours) and the remainder (seconds) in one step, making unit conversion much cleaner.
Exercise 19: Business Days Calculator
Practice Problem: Create a function that takes a start date and an integer N, then calculates the date exactly N business days (Monday–Friday) in the future.
Exercise Purpose: In professional settings (finance, shipping, legal), weekends are ignored. This exercise teaches you how to manipulate dates using a loop while applying conditional logic to “skip” specific days of the week.
Given Input: Start: Friday, 2026-01-02, Days to add: 5
Expected Output:
Start: Friday, 2026-01-02 Business Target: Friday, 2026-01-09
+ Hint
Use a while loop that increments the date by one day at a time, but only decrements the “days to add” counter if the day of the week is less than 5 (Monday=0, Friday=4).
+ Show Solution
Explanation of Solution:
current_date.weekday(): This method is the key to identifying weekends.timedelta(days=1): This allows us to “step” through the calendar physically.strftime: We use this to format the output into a human-readable string that includes the name of the day, proving the weekends were skipped.
Exercise 20: Custom Iterator Class
Practice Problem: Create a class PowerOfTwo that allows you to iterate through powers of 2 (1, 2, 4, 8…) up to a specified maximum exponent.
Exercise Purpose: To understand how Python’s for loop works under the hood, you must implement the Iterator Protocol. This requires two magic methods: __iter__ (which returns the iterator object itself) and __next__ (which returns the next value or raises StopIteration).
Given Input: powers = PowerOfTwo(3)
Expected Output: 1 2 4 8
+ Hint
- Keep a
current_exponentstate inside the class. - Increment it in
__next__until it exceeds themax_exponent.
+ Show Solution
Explanation of Solution:
__iter__: This is called when you start theforloop. It tells Python, “I am an object that can be stepped through.”__next__: This is called on every single iteration of the loop.raise StopIteration: This is the signal Python looks for to know the loop has finished. Without this, theforloop would run forever.- Statefulness: Unlike a standard function, the class remembers exactly where it is in the counting process (
self.n).
Exercise 21: Find Duplicates in O(n) Time
Practice Problem: Write a function that identifies all duplicate elements in a list. The solution must run in linear time, meaning you should only traverse the list once.
Exercise Purpose: Many beginners use nested loops to find duplicates, resulting in O(n2) complexity (very slow for large data). This exercise teaches you to use a Set as a lookup table. Since checking if an item exists in a set takes O(1) (constant time), the entire operation stays highly efficient.
Given Input: numbers = [1, 2, 3, 2, 4, 5, 1, 6]
Expected Output: Duplicates found: {1, 2}
+ Hint
- Create an empty set called
seen. - As you iterate through the list, check if the current number is already in
seen. If it is, it’s a duplicate.
+ Show Solution
Explanation of Solution:
seen = set(): We use a set because it uses a hash table for lookups, makingif x in seennearly instantaneous regardless of the set’s size.- The Single Loop: Because we only go through the list once, the time complexity is O(n).
duplicates.add(x): We store duplicates in a set as well to ensure that if a number appears three times, it is only reported once in our results.
Exercise 22: Singly Linked List Implementation
Practice Problem: Create a basic Node class and a LinkedList class. Implement a method to append a new node to the end of the list and a method to display the list.
Exercise Purpose: Python handles memory automatically, but understanding Linked Lists is fundamental for technical interviews and understanding how data is structured in memory. This exercise introduces Pointer logic (referencing one object from another).
Given Input: List operations: Append 10, Append 20, Append 30
Expected Output: 10 -> 20 -> 30 -> None
+ Hint
- Each
Nodeshould havedataandnext. TheLinkedListshould keep track of theheadnode. - To append, you must start at the head and follow the
nextpointers until you reach a node wherenextisNone.
+ Show Solution
Explanation of Solution:
self.next = None: In Python,Noneacts like theNULLpointer in C. It signifies the end of the chain.while last.next: This loop “traverses” the list. We keep moving thelastpointer until we find the node that doesn’t point to anything yet.- Object Referencing: Unlike arrays, which sit in a contiguous block of memory, these nodes can be anywhere; they are only connected because each object holds a reference to the next.
Exercise 23: Stack Implementation (LIFO)
Practice Problem: Implement a Stack data structure using a Python list. Create methods for push (add), pop (remove), and peek (view top element).
Exercise Purpose: Stacks follow the Last-In, First-Out (LIFO) principle. They are used in “Undo” features in software and the “Back” button in browsers. This exercise teaches you how to restrict access to a list to follow a specific architectural pattern.
Given Input: Push: "google.com", "pynative.com" | Action: Pop
Expected Output:
Current Top: pynative.com
Popped: pynative.com
New Top: google.com
+ Hint
In Python, list.append() and list.pop() are highly optimized for adding/removing from the end of the list, making them perfect for stack operations.
+ Show Solution
Explanation of Solution:
self.items.pop(): Without arguments,pop()removes the last item added, satisfying the LIFO requirement.self.items[-1]: This is a Pythonic way to look at the last item in a list without removing it.- Encapsulation: By wrapping the list in a class, we prevent users from accidentally removing items from the middle of the stack.
Exercise 24: Queue Implementation (FIFO)
Practice Problem: Implement a Queue data structure using collections.deque. Create methods for enqueue (add to back) and dequeue (remove from front).
Exercise Purpose: Queues follow First-In, First-Out (FIFO). Using a standard Python list for a queue is slow because removing the first item (list.pop(0)) requires shifting all other items in memory. deque (Double Ended Queue) is designed to make adding/removing from both ends O(1).
Given Input: Enqueue: "Customer A", "Customer B" | Action: Dequeue
Expected Output:
Serving: Customer A
Next in line: Customer B
+ Hint
Use append() for enqueue and popleft() for dequeue.
+ Show Solution
Explanation of Solution:
deque: Short for “double-ended queue,” it is a memory-efficient container that provides fast appends and pops from both ends.popleft(): This is the key method. It removes the very first item added without having to re-index the rest of the collection.- Real-world Use: This is how task schedulers and print queues operate.
Exercise 25: Recursive Binary Search
Practice Problem: Implement the Binary Search algorithm recursively to find a target value in a sorted list.
Exercise Purpose: While you saw the iterative version in C, implementing it recursively in Python helps you understand how the Call Stack works. You split the problem into “sub-problems” until you reach a base case.
Given Input: Sorted List: [10, 20, 30, 40, 50, 60], Target: 50
Expected Output: Target found at index: 4
+ Hint
- Your function needs four parameters:
(arr, low, high, x). - If
low > high, the target isn’t there. Otherwise, calculatemidand call the function again on either the left or right half.
+ Show Solution
Explanation of Solution:
// 2: This is “floor division” in Python. It ensures the middle index is always an integer.- The Return Chain: Each recursive call returns its result back up the chain. When the base case (
arr[mid] == x) is eventually met, the index value is passed back through all previous function calls to the original caller. - Efficiency: Just like the iterative version, this has
O(log n)complexity, making it extremely fast for large, sorted datasets.
Exercise 26: Lambda Sorting with Tuples
Practice Problem: Given a list of tuples representing employees (Name, Age, Salary), sort the list primarily by Salary in descending order.
Exercise Purpose: In Python, the sort() method and sorted() function are powerful, but they need help when dealing with complex objects. A lambda function is a small, anonymous “throwaway” function that tells Python exactly which part of the data structure to use as the sorting key.
Given Input:
employees = [("Alice", 30, 50000), ("Bob", 25, 75000), ("Charlie", 35, 60000)]Code language: Python (python)
Expected Output:
[('Bob', 25, 75000), ('Charlie', 35, 60000), ('Alice', 30, 50000)]
+ Hint
Use the key parameter in the sorted() function. The lambda should return the element at index 2 of the tuple.
+ Show Solution
Explanation of Solution:
lambda emp: emp[2]: This is a mini-function that takes an employee tuple and returns the third item (Salary). Python uses these returned values to decide the order.reverse=True: By default, Python sorts in ascending order. This flag flips it to descending.- Stability: Python’s sorting algorithm (Timsort) is stable, meaning if two employees had the same salary, their original relative order would be preserved.
Exercise 27: Map and Filter Combination
Practice Problem: Given a list of numbers, use map() and filter() together to create a list of the squares of only the even numbers.
Exercise Purpose: While list comprehensions are often preferred, understanding map and filter is essential for functional programming and working with large data streams. This exercise teaches you how to chain data transformations: first removing unwanted data, then modifying the rest.
Given Input: nums = [1, 2, 3, 4, 5, 6]
Expected Output: [4, 16, 36]
+ Hint
Use filter() to keep numbers where n % 2 == 0, then wrap that inside a map() that calculates n**2.
+ Show Solution
Explanation of Solution:
filter(lambda x: x % 2 == 0, nums): This creates an iterator that only yields numbers divisible by 2.map(lambda x: x**2, ...): This takes the output of the filter and squares each value.list(...): Functions likemapandfilterreturn “lazy” objects (iterators). They don’t actually do the work until you convert them to a list or loop over them, which saves memory.
Exercise 28: Custom @timer Decorator
Practice Problem: Write a decorator function named @timer that prints how many seconds a function takes to execute. Apply it to a function that simulates a heavy computation using time.sleep().
Exercise Purpose: Decorators are one of Python’s most powerful features. They allow you to “wrap” a function with extra logic (like logging, authentication, or timing) without changing the function’s internal code. This follows the Open-Closed Principle.
Given Input: A function waste_time() that sleeps for 1.5 seconds.
Expected Output: Function 'waste_time' took 1.5023 seconds to run.
+ Hint
A decorator is a function that takes a function as an argument, defines a wrapper inside, and returns that wrapper.
+ Show Solution
Explanation of Solution:
*args, **kwargs: This ensures the decorator can work on any function, regardless of how many arguments it takes.time.perf_counter(): This is preferred overtime.time()for measuring duration because it is a monotonic clock (it doesn’t go backward if the system clock updates).@timer: This is “syntactic sugar” forwaste_time = timer(waste_time).
Exercise 29: Fibonacci Generator (Memory Efficiency)
Practice Problem: Create a generator function that yields Fibonacci numbers up to N. Instead of returning a full list, it should yield values one by one.
Exercise Purpose: If you need to generate a billion numbers, a list would crash your computer’s RAM. A Generator uses the yield keyword to return one value at a time and “pauses” its execution state. This is the key to handling Big Data in Python.
Given Input: n = 8
Expected Output:
First 8 Fibonacci numbers:
0 1 1 2 3 5 8 13
+ Hint
Use a while loop and the yield keyword. Swap values using the Pythonic a, b = b, a + b.
+ Show Solution
Explanation of Solution:
yield a: Instead of finishing the function,yieldsendsaback to the caller and waits. When the loop asks for the next value, the function resumes exactly where it left off.- Memory usage: The memory footprint of this generator is constant (
O(1)), whether you generate 5 numbers or 5 million. a, b = b, a + b: This is a simultaneous assignment. Python calculates the right side entirely before assigning any values, avoiding the need for atempvariable.
Exercise 30: Custom Context Manager (with statement)
Practice Problem: Write a class that acts as a context manager for handling a database-style connection (Don’t do actual database connection, simply printing “Connected” and “Disconnected”). Use the with statement to ensure the connection is closed even if an error occurs.
Exercise Purpose: Managing resources like files, network sockets, or database connections is risky. If you forget to close them, you get memory leaks. Context managers automate this using the __enter__ and __exit__ magic methods.
Given Input: A block of code inside a with statement that might raise an Exception.
Expected Output:
Connecting to Database... Processing data...
Error: something went wrong
Closing Database Connection safely.
+ Hint
The __enter__ method sets up the resource, and __exit__ is guaranteed to run at the end of the with block, even if an exception was raised.
+ Show Solution
Explanation of Solution:
__enter__: This runs the moment thewithblock starts.__exit__: This is the “cleanup” phase. It receives information about any errors that happened inside the block (exc_type, etc.).- Safety: Notice that even though we raised an Exception, “Closing Database Connection safely” still printed. This is why we use
withfor file handling (with open(...))—it prevents data corruption.
Exercise 31: The Versatile *args and **kwargs
Practice Problem: Create a “Logger” function that accepts a mandatory message string, followed by an unknown number of positional arguments (*args), and an unknown number of keyword arguments (**kwargs). The function should print the message, then list the extra arguments and metadata.
Exercise Purpose: Intermediate Pythonistas must write functions that are flexible. *args (tuples) and **kwargs (dictionaries) allow your functions to handle dynamic inputs. This is how major libraries like Django or Flask allow for highly customizable function calls.
Given Input:
log_event("User Login", "admin", "dashboard", timestamp="10:00 AM", status="Success")Code language: Python (python)
Expected Output:
Event: User Login
Details: ('admin', 'dashboard')
Metadata: {'timestamp': '10:00 AM', 'status': 'Success'}
+ Hint
Inside the function, args behaves like a tuple and kwargs behaves like a dictionary.
+ Show Solution
Explanation of Solution:
*args: The asterisk unpacks any extra positional arguments into a tuple. This is useful when you don’t know how many items a user will pass.**kwargs: The double asterisk unpacks named arguments into a dictionary. This is perfect for optional configuration settings.- Order Matters: In a function definition, parameters must follow this order: standard arguments,
*args, then**kwargs.
Exercise 32: Zip and Enumerate Mapping
Practice Problem: You have two separate lists: one of student names and one of their exam scores. Use zip() to combine them into a dictionary, then use enumerate() to print a ranked list (1st, 2nd, 3rd…).
Exercise Purpose: Data often arrives in separate “columns” (lists). zip() is the standard Pythonic way to merge these columns. enumerate() is a cleaner alternative to using range(len(list)) when you need both the index and the value of an item.
Given Input:
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]Code language: Python (python)
Expected Output:
Rank 1: Bob scored 92
Rank 2: Alice scored 85
Rank 3: Charlie scored 78
+ Hint
First, create a dictionary. Then, sort the dictionary items by value in descending order before enumerating.
+ Show Solution
Explanation of Solution:
zip(names, scores): This creates pairs like('Alice', 85). Passing this todict()creates a lookup table instantly.enumerate(..., start=1): By default, enumerate starts at 0. Settingstart=1makes the output user-friendly for rankings.- Unpacking in Loop: The syntax
i, (name, score)allows us to unpack the index and the tuple returned byitems()in a single step.
Exercise 33: Memoization with lru_cache
Practice Problem: Write a recursive function fibonacci(n) to calculate the nth number in the Fibonacci sequence. Use functools.lru_cache to optimize it so that it doesn’t recalculate the same values multiple times.
Exercise Purpose: Recursive functions for Fibonacci are notoriously slow (O(2n)) because they recalculate the same branches of the “recursion tree” over and over. Memoization stores the results of expensive function calls. Python’s lru_cache (Least Recently Used) is a built-in decorator that handles this automatically.
Note: Without cache, this would take minutes; with cache, it’s instant.
Given Input: fibonacci(50)
Expected Output:
Fibonacci(50) = 12586269025
+ Hint
Import lru_cache from functools and place @lru_cache(maxsize=None) above your function.
+ Show Solution
Explanation of Solution:
@lru_cache: Whenfibonacci(5)is called, the result is saved in a hidden dictionary. The next time the code needsfibonacci(5), it simply grabs the result from memory.maxsize=None: This tells Python the cache can grow as large as needed.cache_info(): This allows you to see how many “hits” (reused values) and “misses” (newly calculated values) occurred, proving the efficiency.
Exercise 34: Set Operations for Data Analysis
Exercise Purpose: Sets are not just for removing duplicates; they are powerful mathematical tools for comparing collections. Using set logic is much faster and more readable than writing multiple for loops with if conditions.
Given Input:
trial = [1, 2, 3, 4, 5]
paid = [4, 5, 6, 7, 8]Code language: Python (python)
Expected Output:
Upgraded (Both): {4, 5}
Leads (Trial only): {1, 2, 3}
Unique Status (Not both): {1, 2, 3, 6, 7, 8}
+ Hint
Use the operators & (intersection), - (difference), and ^ (symmetric difference).
+ Show Solution
Explanation of Solution:
&(Intersection): Returns only elements present in both sets.-(Difference): Returns elements in the first set that are not in the second.^(Symmetric Difference): Returns elements that are in one of the sets, but not both.- Performance: These operations are highly optimized at the C level in Python, making them the most efficient way to compare large datasets.
Exercise 35: Inheritance and Method Overriding
Practice Problem: Create a base class Vehicle with an attribute called brand and a method fuel_type(). Then, create a subclass ElectricCar that inherits from Vehicle and overrides the fuel_type() method to return “Electricity.”
Exercise Purpose: Inheritance allows you to define a general behavior in a “parent” class and then specialize it in a “child” class. This prevents code duplication (DRY—Don’t Repeat Yourself) and creates a logical hierarchy in your software.
Given Input: car = ElectricCar("Tesla")
Expected Output:
Brand: Tesla
Fuel Type: Electricity
+ Hint
Use the super().__init__(brand) call in the child class to ensure the parent class is properly initialized.
+ Show Solution
Explanation of Solution:
class ElectricCar(Vehicle): This syntax tells Python thatElectricCaris a specialized version ofVehicle.- Method Overriding: By defining
fuel_type()again in the child class, we replace the parent’s logic with something specific to electric cars. - Inheritance of Attributes: Notice we didn’t define
self.brandinsideElectricCar; it was automatically inherited from theVehicleclass.
Exercise 36: Encapsulation (Private Attributes)
Practice Problem: Create a BankAccount class where the balance is a private attribute (cannot be accessed directly from outside the class). Provide deposit and withdraw methods to modify the balance safely.
Exercise Purpose: Encapsulation is about data protection. By making attributes private, you prevent external code from accidentally setting a balance to a negative number or a string. You force all changes to go through “gatekeeper” methods.
Given Input:
account = BankAccount(100)
account.deposit(50)
account.withdraw(200) # This should trigger a warningCode language: Python (python)
Expected Output:
Deposited 50.
New Balance: 150
Insufficient funds! Final Balance: 150
+ Hint
In Python, prefixing an attribute with two underscores (e.g., self.__balance) makes it “private” through name mangling.
+ Show Solution
Explanation of Solution:
self.__balance: The double underscore tells Python to hide this variable. If you try to runprint(acc.__balance)outside the class, it will raise anAttributeError.- Validation: The
withdrawmethod includes anifstatement to check if the user has enough money. This is the “gatekeeper” logic that encapsulation enables. - Getter Method: Since the attribute is private, we provide
get_balance()to let users see the data without being able to corrupt it.
Exercise 37: Property Decorators (@property)
Practice Problem: Create a Student class with a name and a score. Use the @property decorator to create a getter for the score, and a @score.setter to ensure that any score assigned is between 0 and 100.
Exercise Purpose: Property decorators allow you to treat a method like an attribute. This is “Pythonic” because it allows you to add validation logic (like checking the 0–100 range) later in development without changing the way users interact with your class.
Given Input:
s = Student("Kevin")
s.score = 105 # Should trigger a ValueErrorCode language: Python (python)
Expected Output: ValueError: Score must be between 0 and 100.
+ Hint
The actual data should be stored in a “protected” variable like self._score (single underscore).
+ Show Solution
Explanation of Solution:
@property: This turns thescore()method into a “getter.” You access it vias.scoreinstead ofs.score().@score.setter: This method is triggered when you try to use the=operator. It allows for “invisible” data validation.- Refactoring: This is extremely useful for maintaining backward compatibility in large codebases.
Exercise 38: Class Methods vs. Static Methods
Practice Problem: Create a class Pizza that has a price attribute. Implement a @classmethod called margherita() that returns a pre-configured Pizza object and a @staticmethod called validate_topping() that checks if a topping is “healthy.”
Exercise Purpose: 1. Class Methods are “Factory” methods; they have access to the class (cls) and are used to create specific instances. 2. Static Methods are “Utility” methods; they live inside the class for organization but don’t need access to class or instance data.
Given Input:
my_pizza = Pizza.margherita()
is_valid = Pizza.validate_topping("pineapple")Code language: Python (python)
Expected Output:
Pizza ordered: Margherita
Is topping valid? True
+ Hint
Use @classmethod with cls as the first argument, and @staticmethod with no special first argument.
+ Show Solution
Explanation of Solution:
cls(...): Inside a class method,clsrefers to thePizzaclass itself. Callingcls()is the same as callingPizza().- Organization: Static methods help keep related logic inside the class rather than floating around as global functions.
- Factory Pattern: Class methods are great for providing “presets” (like different types of pizzas or different ways to load data).
Exercise 39: Magic Methods (__str__ and __add__)
Practice Problem: Create a Point class that represents (x, y) coordinates. Implement __str__ so that printing the object looks like (x, y) and implement __add__ so that p1 + p2 adds the coordinates together.
Exercise Purpose: “Magic methods” (or Dunder methods) allow your custom objects to “hook into” Python’s built-in syntax. By implementing __add__, you tell Python what the + sign should do when it encounters your objects.
Given Input:
p1 = Point(1, 2)
p2 = Point(3, 4)
print(p1 + p2)Code language: Python (python)
Expected Output: (4, 6)
+ Hint
__add__ should return a new instance of the Point class.
+ Show Solution
Explanation of Solution:
__str__: Without this, printing the object would result in a messy memory address like<__main__.Point object at 0x... >.selfandother: In__add__,selfis the object on the left of the+andotheris the object on the right.- Operator Overloading: This makes your custom objects feel like “first-class citizens” in Python, just like integers or strings.
Exercise 40: Abstract Base Classes (ABC)
Practice Problem: Create an abstract base class Shape with an abstract method area(). Then, implement two subclasses, Circle and Square, that provide the actual logic for calculating their respective areas.
Exercise Purpose: Abstract Base Classes (ABCs) act as a contract. They define a set of methods that all subclasses must implement. If you try to instantiate a subclass that hasn’t defined area(), Python will raise an error. This is vital for building large frameworks where you want to ensure consistency across many different modules.
Given Input: shapes = [Circle(5), Square(4)]
Expected Output:
Circle Area: 78.54 Square Area: 16
+ Hint
Use the abc module and the @abstractmethod decorator.
+ Show Solution
Explanation of Solution:
ABC: Inheriting fromABCprevents you from creating a genericShape()object.@abstractmethod: This “marks” the method. Python will now block any subclass from being created unless it overrides this specific method.- Polymorphism: In the loop, we call
.area()on different objects without needing to know their specific type. This is the heart of flexible software design.
Exercise 41: Multiple Inheritance and MRO
Practice Problem: Create two classes, Flyer (with a fly() method) and Swimmer (with a swim() method). Create a Duck class that inherits from both. Use the __mro__ attribute to inspect the search order.
Exercise Purpose: Python allows a class to inherit from multiple parents. However, this can get complicated (the “Diamond Problem”). This exercise teaches you how Python resolves which method to call using the Method Resolution Order (MRO).
Given Input:
d = Duck()
d.fly()
d.swim()Code language: Python (python)
Expected Output:
Flying high!
Swimming fast!
MRO: (<class '__main__.Duck'>, <class '__main__.Flyer'>, <class '__main__.Swimmer'>, <class 'object'>)
+ Hint
Simply list both parent classes in the parentheses: class Duck(Flyer, Swimmer):
+ Show Solution
Explanation of Solution:
- Multiple Inheritance:
Ducknow possesses all methods from bothFlyerandSwimmer. - MRO (Method Resolution Order): Python uses the C3 Linearization algorithm to determine the order in which it searches for methods. You can see this by checking
ClassName.__mro__. - Object: Every class in Python 3 ultimately inherits from the built-in
objectclass, which is why it appears last in the MRO.
Exercise 42: Composition over Inheritance
Practice Problem: Build a Computer class that is “composed” of a CPU object and a RAM object, rather than inheriting from them.
Exercise Purpose: A common mantra in software engineering is “Compose instead of Inherit.” While inheritance implies a “is-a” relationship (a Dog is a Mammal), composition implies a “has-a” relationship (a Computer has a CPU). This makes your code more modular and easier to change later.
Given Input: my_comp = Computer("Intel i7", "16GB")
Expected Output: Computer with Intel i7 CPU and 16GB RAM.
+ Hint
Instantiate the CPU and RAM objects inside the Computer‘s __init__ method.
+ Show Solution
Explanation of Solution:
- Decoupling: The
Computerclass doesn’t need to know how aCPUworks; it just knows it has one. - Flexibility: If you wanted to swap the CPU for a different brand later, you only change the internal object, not the entire inheritance tree of the class.
Exercise 43: The Singleton Pattern
Practice Problem: Implement a Database class that ensures only one instance of itself can ever exist. If a user tries to create a second instance, it should return the first one created.
Exercise Purpose: Sometimes, you need exactly one instance of a class to coordinate actions across a system (like a log file manager or a database connection pool). This exercise introduces the __new__ magic method, which controls the actual creation of the object (before __init__ even runs).
Given Input:
db1 = Database()
db2 = Database()
print(db1 is db2)Code language: Python (python)
Expected Output:
Loading Database... True (Both variables point to the same memory address)
+ Hint
Store the instance in a class-level variable. Check if it exists in __new__.
+ Show Solution
Explanation of Solution:
__new__: This method is the actual “constructor.” It returns the object instance.cls._instance: By checking this variable, we ensure that the call tosuper().__new__only happens once.isoperator: In Python,ischecks for identity (memory address), whereas==checks for equality (value). For a Singleton,ismust return True.
Exercise 44: Data Classes (@dataclass)
Practice Problem: Refactor a standard Book class (with title, author, and pages) into a dataclass. Show how it automatically handles __init__ and __repr__.
Exercise Purpose: Writing self.x = x fifty times in a large project is tedious. Python 3.7+ introduced dataclasses to automatically generate “boilerplate” code like __init__, __repr__ (printable representation), and __eq__. It makes your code cleaner and faster to write.
Given Input: b1 = Book("1984", "George Orwell", 328)
Expected Output: Book(title='1984', author='George Orwell', pages=328)
+ Hint
Use from dataclasses import dataclass and simply list the attributes with type hints.
+ Show Solution
Explanation of Solution:
- Type Hints: Dataclasses require type hints (e.g.,
: str). While Python doesn’t strictly enforce these at runtime, they are necessary for the dataclass generator to work. __repr__: Notice thatprint(b1)actually shows the data, unlike a standard class which would show a memory address.__eq__: Dataclasses automatically implement equality logic based on the data values, making them perfect for “Data Transfer Objects” (DTOs).
Exercise 45: CSV Processor
Practice Problem: Write a script that reads a CSV file containing employee names and salaries. Calculate the average salary and write the results (Original Data + Average) into a new CSV file.
Exercise Purpose: CSV (Comma-Separated Values) is the most common format for data exchange. This exercise teaches you to use the built-in csv module, specifically DictReader and DictWriter, which allow you to treat rows as dictionaries rather than just lists of strings.
Given Input (data.csv):
Name,Salary
Alice,50000
Bob,60000
Charlie,70000
Expected Output:
output.csv:
Includes the original data and a final row: Average,60000.0.
+ Hint
Use DictReader to automatically map the header to values. Remember to convert salary strings to integers for math.
+ Show Solution
Explanation of Solution:
DictReader: This is safer than basicreaderbecause it lets you access columns by name (row['Salary']) rather than index (row[1]). This makes your code break-resistant if columns are rearranged.newline='': This is a standard Python practice when opening files for thecsvmodule to prevent blank lines from being inserted between rows on different operating systems.- Context Managers: We use
with open(...)to ensure the file is closed automatically, preventing data corruption.
Exercise 46: JSON Parser and Nested Access
Practice Problem: Given a JSON string representing a user profile with nested settings, parse the string and safely update a specific nested value (e.g., changing the “theme” from “light” to “dark”).
Exercise Purpose: JSON is the language of the web. Most APIs send and receive data in this format. This exercise teaches you how to convert between Python objects (dictionaries/lists) and JSON strings using the json module.
Given Input:
user_json = '{"id": 1, "profile": {"name": "Alice", "settings": {"theme": "light"}}}'Code language: Python (python)
Expected Output:
Updated JSON: {"id": 1, "profile": {"name": "Alice", "settings": {"theme": "dark"}}}
+ Hint
Use json.loads() (load string) to convert to a dictionary, and json.dumps() (dump string) to convert back to JSON format.
+ Show Solution
Explanation of Solution:
json.loadsvsjson.load:loads(with an ‘s’) is for Strings;loadis for file objects.- Nested Dictionaries: JSON data is parsed into nested Python dictionaries. You access deep values by “chaining” keys:
data[key1][key2]. indent=4: This argument indumpsmakes the output “pretty” and human-readable rather than one long, cramped line.
Exercise 47: Regular Expressions (Email Extractor)
Practice Problem: Write a script that takes a long block of messy text and extracts all valid email addresses using the re module.
Exercise Purpose: Regular Expressions (Regex) are a language within a language. They are used for advanced pattern matching. Instead of writing complex loops to search for an “@” and a “.”, Regex allows you to define a “template” that describes what an email looks like.
Given Input:
text = "Contact us at support@company.com or sales.dept@office.org for help."Code language: Python (python)
Expected Output: ['support@company.com', 'sales.dept@office.org']
+ Hint
A simple email pattern is [\w\.-]+@[\w\.-]+\.\w+.
+ Show Solution
Explanation of Solution:
r'...': Therstands for “raw string.” It tells Python not to treat backslashes as special characters, which is essential for Regex.re.findall(): This function scans the entire string and returns all matches as a list.[a-zA-Z0-9._%+-]+: This part of the pattern matches the username portion (letters, numbers, and certain symbols like dots).
Exercise 48: Robust Error Handling (Try/Except/Finally)
Practice Problem: Write a function divide_numbers(a, b) that handles ZeroDivisionError and TypeError (if the user passes a string). Use a finally block to print “Operation complete” regardless of the outcome.
Exercise Purpose: Real-world code fails. Users enter text where they should enter numbers, and servers go offline. Professional Pythonistas use try/except to “catch” these errors gracefully so the entire program doesn’t crash.
Given Input:
divide_numbers(10, 2)divide_numbers(10, 0)divide_numbers(10, "apple")
Expected Output:
Result: 5.0
Operation complete.
--------------------
Error: Cannot divide by zero!
Operation complete.
--------------------
Error: Please provide numbers (integers or floats).
Operation complete.
+ Hint
You can catch multiple exceptions by using multiple except blocks.
+ Show Solution
Explanation of Solution:
- Specific Exceptions: Always catch specific errors (like
ZeroDivisionError) before catching the generalException. This helps in debugging. finally: This block is guaranteed to run. It is usually used for cleaning up resources, like closing a database connection or a file.- Graceful Failure: Instead of the program stopping abruptly with a “Traceback,” the user gets a helpful message, and the program continues.
Exercise 49: OS Module (File Searcher)
Practice Problem: Write a function that walks through a directory and all of its subdirectories, printing the full path of every .txt file it finds.
Exercise Purpose: Being able to navigate the file system programmatically is a core skill for automation. The os.walk() function is a powerful generator that handles the complex recursion of folders for you.
Given Input: A root directory name.
Expected Output:
Found: /Users/name/Documents/notes.txt
Found: /Users/name/Documents/Work/todo.txt
+ Hint
os.walk(path) yields three values: the current root, the dirs in that root, and the files in that root.
+ Show Solution
Explanation of Solution:
os.walk(): This function does the heavy lifting of recursion. It keeps “walking” down into sub-folders until there are none left.os.path.join(): This is critical for cross-platform compatibility. It uses/on Mac/Linux and\on Windows so your code doesn’t break when shared.- Filtering: We use
.endswith(".txt")to pick only the files we care about, a common pattern in data processing scripts.
Exercise 50: Multi-threading (Concurrency)
Practice Problem: Use the threading module to run two functions simultaneously. One function should “Download File A” and the other “Download File B” (using time.sleep to simulate the delay).
Exercise Purpose: Python is often “I/O bound,” meaning it spends a lot of time waiting for things (like web downloads). Threading allows your program to do other work while waiting, effectively running tasks in parallel and saving time.
Given Input: Two tasks taking 2 seconds each.
Expected Output:
Total time taken: 2 seconds (instead of 4 seconds).
+ Hint
Create threading.Thread objects and use .start() to begin them and .join() to wait for them to finish.
+ Show Solution
Explanation of Solution:
targetandargs: We pass the function name totargetand its arguments as a tuple toargs.start(): This tells the OS to begin executing the function in a separate thread.join(): This is a “blocker.” It tells the main program: “Don’t finish the script until these threads are done.” Without this, the script might end before the downloads finish.
Exercise 51: API Requests with Error Handling
Practice Problem: Use the requests library to fetch data from a public API (like JSONPlaceholder). Handle potential connection errors or timeouts using a try/except block.
Exercise Purpose: Most modern Python applications rely on third-party APIs. Learning to handle the “unreliability” of the internet (timeouts, 404 errors, 500 server errors) is what makes a script “robust.”
Given Input:
URL = "https://jsonplaceholder.typicode.com/todos/1"Code language: Python (python)
Expected Output:
Status Code: 200 Data: {'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}
+ Hint
Use response.raise_for_status() to automatically raise an error for bad status codes (like 404 or 500).
+ Show Solution
Explanation of Solution:
timeout=5: Never make a request without a timeout! If the server is hanging, your program will wait forever unless you set a limit.response.json(): Therequestslibrary has a built-in parser that converts JSON strings directly into Python dictionaries.raise_for_status(): This is a clean way to handle errors like “404 Not Found” without writing dozens ofif/elsestatements.
Exercise 52: Word Frequency Counter
Practice Problem: Write a function that takes a paragraph of text and returns a dictionary where the keys are unique words and the values are the number of times those words appear. Ensure the counter is case-insensitive and ignores punctuation.
Exercise Purpose: This combines string cleaning (regex or string methods) with dictionary logic. It’s a foundational task for Natural Language Processing (NLP) and data analysis.
Given Input:
text = "Python is great. Python is fast, and learning Python is fun!"Code language: Python (python)
Expected Output:
{'python': 3, 'is': 3, 'great': 1, 'fast': 1, 'and': 1, 'learning': 1, 'fun': 1}
+ Hint
Use .lower() for case-insensitivity and .replace() or re.sub() to remove commas and periods before splitting the string into a list.
+ Show Solution
Explanation of Solution:
re.sub(r'[^\w\s]', '', text): This regular expression removes anything that isn’t a word character or whitespace. It keeps “Python is fast” from becoming “fast,” (with the comma)..split(): By default, this splits by any whitespace, turning the string into a list of individual words.Counter: As seen in earlier exercises, this is the most efficient way to tally items in an iterable.
Exercise 53: Student Management System
Practice Problem: Create a system using a dictionary of dictionaries to manage student records. Implement functions to add_student, update_grade, and display_all. Each student should have a unique ID.
Exercise Purpose: This exercise teaches you how to manage Nested Data Structures. In Python, dictionaries are often used as “in-memory databases” before transitioning to actual SQL or NoSQL databases.
Given Input:
- Add ID 101: “Alice”, Grade: “A”
- Update ID 101: Grade: “A+”
Expected Output: ID: 101 | Name: Alice | Grade: A+
+ Hint
Use the student ID as the “primary key” (the main dictionary key) and another dictionary as the value to store the name and grade.
+ Show Solution
Explanation of Solution:
students[s_id]: Using the ID as a key allows for O(1) (instant) lookups, which is much faster than searching through a list of students.- Nested Access:
students[s_id]["grade"]shows how we drill down into the inner dictionary to modify specific data. - Membership Testing:
if s_id in studentsprevents the program from crashing if we try to update a non-existent ID.
Exercise 54: Password Strength Checker
Practice Problem: Write a function that takes a string and returns a “Strength Score” (0–5). The password gets 1 point for meeting each criteria: 8+ characters, has uppercase, has lowercase, has a digit, and has a special character (e.g., !, @, #).
Exercise Purpose: This reinforces the use of Boolean Logic and string character testing methods like .isupper(), .isdigit(), and the any() function.
Given Input: "P@ss123"
Expected Output: Strength: 5/5 (Very Strong)
+ Hint
Create a list of boolean checks and use sum() on that list. In Python, True equals 1 and False equals 0.
+ Show Solution
Explanation of Solution:
any(...)with a Generator:any(char.isdigit() for char in password)is a very efficient way to check if at least one character meets the criteria without writing a full loop.not char.isalnum(): This is a clever way to detect special characters. If a character is neither a letter (alpha) nor a number (numeric), it must be a symbol or space.sum(checks): SinceTrueis treated as1, summing the list of booleans gives us the final score instantly.
Exercise 55: Number Guessing Game (Computer vs User)
Practice Problem: Create a game where the computer picks a random number between 1 and 100. The user has 10 attempts to guess it. After each guess, the computer tells the user if the actual number is “Higher” or “Lower.”
Exercise Purpose: This project focuses on Control Flow (while-loops) and the random module. It also introduces basic User Input Validation to ensure the game doesn’t crash if a user types something that isn’t a number.
Given Input: Target: 42 | User Guess: 50
Expected Output:
I'm thinking of a number between 1 and 100.
(10 left) Enter guess: 45
Higher!
(9 left) Enter guess: 97
Lower!
(8 left) Enter guess: 52
Higher!
(7 left) Enter guess: 85
Lower!
(6 left) Enter guess: 93
Lower!
(5 left) Enter guess: 54
Correct! The number was 54.
+ Hint
Use random.randint(1, 100) and a while loop that continues as long as the guess is wrong and attempts are > 0.
+ Show Solution
Explanation of Solution:
random.randint(1, 100): This includes both endpoints (1 and 100) in the possible range.try/except: Wrappingint(input())is essential because users often enter non-integers by mistake.returninside the loop: This is a clean way to exit the entire function immediately once the correct answer is found.
Exercise 56: File Word Count Tool
Practice Problem: Write a script that reads a text file and prints the total number of lines, words, and characters (including spaces).
Exercise Purpose: This mimics the Unix wc (word count) command. It teaches you how to efficiently process a file line-by-line, which is a key skill for working with large logs or text datasets.
Given Input (sample.txt):
Hello World
Python is fun.
Expected Output: Lines: 2 | Words: 5 | Characters: 27
+ Hint
- You can iterate over a file object directly to get lines.
- Use
len(line)for characters andlen(line.split())for words.
+ Show Solution
Explanation of Solution:
- Line-by-Line Iteration:
for line in fis memory-efficient because Python doesn’t load the entire file into RAM at once—it only reads one line at a time. len(line): This includes the newline character (\n) at the end of each line, which is standard for “character counts” in most editors.with open(...): Ensuring the file is automatically closed prevents system resource leaks.
Exercise 57: Prime Number Generator
Practice Problem: Write a function that takes a range (start and end) and returns a list of all prime numbers within that range. Optimize the check by only testing divisors up to the square root of the number.
Exercise Purpose: This exercise sharpens your understanding of nested loops and mathematical optimization. Checking divisors up to sqrt{n} significantly improves performance compared to checking every number up to n.
Given Input: Range: 10 to 50
Expected Output:
Primes: [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
+ Hint
- A number is prime if it is greater than 1 and has no divisors other than 1 and itself.
- Use
num**0.5to find the square root.
+ Show Solution
Explanation of Solution:
int(n**0.5) + 1: This is the mathematical shortcut. If a factor exists, at least one must be less than or equal to the square root of n.range(start, end + 1): We add 1 to the end because Python’srangeis exclusive of the final value.- List Comprehension: We use a clean one-liner to filter the range based on our
is_primehelper function.
Exercise 58: Email Validation Program
Practice Problem: Create a script that asks for an email address and validates it against a comprehensive Regular Expression. It should check for a username, the @ symbol, a domain name, and a valid top-level domain (like .com or .org).
Exercise Purpose: While basic string methods can find an “@” sign, only Regular Expressions (Regex) can ensure the structure of the email is truly valid according to web standards.
Given Input:
email1 = "python_pro@gmail.com"
email2 = "bad-email@com"Code language: Python (python)
Expected Output:
'python_pro@gmail.com' is a Valid Email 'bad-email@com' is an Invalid Email
+ Hint
- Use the
remodule and thematch()function. - A common pattern is
^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$.
+ Show Solution
Explanation of Solution:
^and$: These anchor the search to the start and end of the string, ensuring no extra “garbage” characters are hidden at the ends.\w+: This matches one or more alphanumeric characters.\w{2,3}: This ensures the extension (like .com or .in) is at least 2 or 3 characters long.
Exercise 59: File-Based To-Do List App
Practice Problem: Build a simple CLI app that allows users to add tasks to a text file, view the current list, and “clear” the list. The tasks should persist even after the program is closed.
Exercise Purpose: This introduces Persistent Storage. Instead of data disappearing when the script ends (RAM), we save it to the hard drive (Disk).
Given Input:
Add Task: "Buy Milk"
Add Task: "Finish Python Project"
Expected Output:
--- My To-Do List ---
1. Buy Milk
2. Finish Python Project
+ Hint
- Use
a(append) mode to add tasks without deleting old ones. - Use
r(read) mode to display them.
+ Show Solution
Explanation of Solution:
"a"Mode: This “appends” the new text to the end of the existing file.strip(): When reading from a file, each line ends with a newline character (\n).strip()removes that extra whitespace so our display looks clean.open(FILE_NAME, "w").close(): Opening a file in “write” mode immediately wipes the contents. Closing it immediately leaves us with a clean, empty file.
Exercise 60: Random Password Generator
Practice Problem: Write a script that generates a random, secure password. The user should be able to specify the desired length, and the password must include a mix of uppercase letters, lowercase letters, numbers, and symbols.
Exercise Purpose: This project teaches you to use the secrets module (which is more secure than random for passwords) and the string module, which contains pre-defined constants like all letters and punctuation.
Given Input: Length: 12
Expected Output: Generated Password: 4k#79!zP[2mQ
+ Hint
Combine string.ascii_letters, string.digits, and string.punctuation into one pool of characters.
+ Show Solution
Explanation of Solution:
secrets.choice(): Unlikerandom.choice(), thesecretsmodule generates numbers that are cryptographically secure, making them much harder to predict for hackers."".join(...): This takes the individual random characters generated by our loop and “glues” them together into a single string.string.punctuation: This is a built-in Python string that contains all special characters like!"#$%&'()*+,-./:;<=>?@[\]^_{|}~.
Exercise 61: Pascal’s Triangle
Practice Problem: Write a function to generate the first N rows of Pascal’s Triangle. Each number is the sum of the two numbers directly above it. See print patterns in Python.
Exercise Purpose: This is a classic algorithmic challenge that tests your ability to manage indices and nested lists. It requires thinking about the relationship between a current row and the row that came before it.
Given Input: Rows: 5
Expected Output:
[1] [1, 1] [1, 2, 1] [1, 3, 3, 1] [1, 4, 6, 4, 1]
+ Hint
- Every row starts and ends with
1. - The middle numbers are calculated as
row[j] = prev_row[j-1] + prev_row[j].
+ Show Solution
Explanation of Solution:
triangle[-1]: This is a Pythonic way to grab the very last row we generated.- The
jLoop: This inner loop only runs for rows larger than 2, calculating the “inner” numbers by looking at the two numbers above them. - List of Lists: The final structure is a nested list where each sub-list represents a row, which is perfect for representing mathematical matrices or triangles.
Exercise 62: Smart Property Decorators
Practice Problem: Create a Circle class with a radius attribute. Implement area as a property. If the user changes the radius, the area should reflect the change automatically without needing a manual function call.
Exercise Purpose: This demonstrates Reactive Programming within OOP. Properties allow you to expose calculated data as if it were a simple variable, ensuring that your object’s internal state is always consistent.
Given Input: c = Circle(5), then c.radius = 10
Expected Output: Initial Area: 78.54 Updated Area: 314.16
+ Hint
Use the @property decorator on the area method. This makes it “read-only” and auto-calculating.
+ Show Solution
Explanation of Solution:
@property: This turns the method into a “getter.” Note that in the print statement, we usec.areainstead ofc.area().- State Sync: Because
areais a function under the hood, it doesn’t “store” the old area; it always calculates it based on the currentself.radius. - Encapsulation: This approach protects the data; the user cannot manually set
c.area = 500because no setter was defined, preventing logical errors.
Exercise 63: Caesar Cipher Implementation
Practice Problem: Implement a function that encrypts a message by shifting each letter by a fixed number of positions in the alphabet. It should handle uppercase, lowercase, and ignore non-alphabetic characters.
Exercise Purpose: This is an introduction to Algorithms and Character Encoding. It teaches you how to use ord() (char to integer) and chr() (integer to char) while using the modulo operator to “wrap around” the alphabet from Z back to A.
Given Input: Message: "Hello!", Shift: 3
Expected Output: "Khoor!"
+ Hint
For any character, the formula is (original_position + shift) % 26.
+ Show Solution
Explanation of Solution:
ord(char) - start: This converts the character’s ASCII value to a 0–25 index (e.g., ‘A’ becomes 0).% 26: This is the “circular” logic. If the shift moves ‘Z’ (index 25) by 1, the modulo brings it back to 0 (‘A’).- Symmetry: To decrypt, you simply pass the negative of the shift value.
Exercise 64: Hollow Triangle Pattern
Practice Problem: Write a script that prints a hollow triangle of height N. The edges should consist of stars (*), but the interior should be empty space.
Exercise Purpose: This challenges your Coordinate Logic. You must determine the exact conditions under which a star should be printed (the first column, the last column, or the last row) versus a space.
Given Input: Height: 5
Expected Output:
*
* *
* *
* *
*********
+ Hint
Use two nested loops. Print a star if it’s the first or last character of a row, or if it’s the bottom row. Otherwise, print a space.
+ Show Solution
Explanation of Solution:
j == n - i + 1: This calculates the left-sloping edge.j == n + i - 1: This calculates the right-sloping edge.i == n: This ensures the bottom row is filled completely.end="": This prevents Python from adding a newline after every single character, allowing us to build the row horizontally.
Exercise 65: Solid Diamond Pattern
Practice Problem: Create a script that prints a solid diamond. The user provides the height of the top half, and the program must mirror it to create the bottom half.
Exercise Purpose: This exercise focuses on Symmetry and Loop Ranges. You must learn how to reverse a range (growth vs. shrink) to ensure the diamond aligns perfectly at its widest point.
Given Input:
Size: 4
Expected Output:
*
***
*****
*******
*****
***
*
+ Hint
- Split the problem into two loops.
- The first loop goes from 1 to n, and the second loop goes from n-1 down to 1.
+ Show Solution
Explanation of Solution:
- tring Multiplication: Python allows you to do
" " * 5, which makes centering patterns much easier than using nested loops for spaces. 2 * i - 1: This mathematical formula ensures that every row has an odd number of stars (1, 3, 5, 7), which is required for a centered diamond.range(n-1, 0, -1): The third parameter-1tells the loop to count backward, creating the inverted triangle for the bottom half.
