10 Python Practice Problems for Beginners Who Know the Basics but Need Hands-On Practice

Sep 2, 2026 | CompeteX

You understand variables, loops, conditions, functions, lists, and dictionaries. But when you open a blank code editor, turning a written requirement into working Python still feels difficult. 

That gap is normal. Knowing Python syntax gives you the building blocks, while hands-on practice teaches you how to select and combine them. The ten Python practice problems below move from short exercises to small data-related tasks. Each includes a hint, solution, explanation, and optional extension so you can practise beyond the first correct answer. 

All examples use standard Python features, so you can run them without installing additional packages. If you need to check unfamiliar syntax, use the official Python tutorial as a reference. 

Exercise validation note: Every code sample in this guide was run in Python 3 with the listed input, and its output was checked against the expected result. The explanations also identify relevant edge cases, including empty inputs, duplicate values, missing fields, and incorrectly formatted records. 

You will learn more if you attempt each problem before reading its solution. Follow this process: 

  1. Rewrite the requirement in your own words. 
  1. Identify the likely inputs, output, and Python concepts involved. 
  1. Write a first solution, even if it is incomplete. 
  1. Test it with the sample data and at least one new case. 
  1. Compare your approach with the provided solution. 
  1. Complete the optional extension without copying the original code. 

A solution does not have to match ours line for line. If it produces the correct result, handles the expected inputs, and you can explain it, your approach may be equally valid. 

1. Clean and Format a User's Name 

Task: Convert a name with inconsistent spaces and capitalisation into a clean display name. 

Sample input: " aNITA SHARMA " 

Expected output: Anita Sharma 

Hint: Combine strip(), split(), join(), and title(). 

raw_name = "  aNITA   SHARMA  " 
 
clean_name = " ".join(raw_name.strip().split()).title() 
print(clean_name) 
 

The code removes spaces from both ends, splits the remaining text wherever one or more spaces occur, joins the words with a single space, and formats them for display. This is a useful introduction to text cleaning. In a production system, remember that .title() may not format every cultural or compound name correctly. 

Try next: Accept the name with input() and reject an entry that contains only spaces. 

2. Calculate a Weekly Expense Summary 

Task: Calculate the total, average, and highest value in a list of daily expenses. 

Sample input: [120, 250, 90, 300, 140, 0, 200] 

Expected output: Total 1100, average 157.14, highest 300 

Hint: Update the total and highest value during the same loop. 

expenses = [120, 250, 90, 300, 140, 0, 200] 
 
total = 0 
highest = None 
 
for amount in expenses: 
    total += amount 
    if highest is None or amount > highest: 
        highest = amount 
 
average = total / len(expenses) if expenses else 0 
 
print("Total:", total) 
print("Average:", round(average, 2)) 
print("Highest:", highest) 
 

This problem combines iteration, accumulation, comparison, and a check that prevents division by zero when the list is empty. 

Try next: Add the day names and print which day had the highest expense. 

3. Find Duplicate Survey Response IDs 

Task: Find every ID that occurs more than once. 

Sample input: [102, 105, 102, 108, 110, 105] 

Expected output: [102, 105] 

Hint: Use one set for IDs you have seen and another for duplicates. 

response_ids = [102, 105, 102, 108, 110, 105] 
 
seen = set() 
duplicates = set() 
 
for response_id in response_ids: 
    if response_id in seen: 
        duplicates.add(response_id) 
    else: 
        seen.add(response_id) 
 
print(sorted(duplicates)) 
 

A set stores unique values and supports fast membership checks. Keeping duplicates in a second set ensures that an ID appears only once in the result, even if it occurs several times in the input. 

Try next: Report how many times each duplicated ID occurs. 

4. Count Different Error Types 

Task: Count how often each log level appears. 

Sample input: ["INFO", "ERROR", "WARNING", "ERROR", "INFO", "ERROR"] 

Expected output: {"INFO": 2, "ERROR": 3, "WARNING": 1} 

Hint: Use the log level as a dictionary key. 

logs = ["INFO", "ERROR", "WARNING", "ERROR", "INFO", "ERROR"] 
 
counts = {} 
 
for level in logs: 
    counts[level] = counts.get(level, 0) + 1 
 
print(counts) 
 

The dictionary connects each category with its running total. The get() method returns zero when a category has not appeared before, avoiding a separate initialisation condition. 

Try next: Print the most frequent log level using max(). 

5. Create a Product Inventory Alert 

Task: Find products with stock at or below a chosen threshold. 

Sample input: {"Keyboard": 7, "Mouse": 2, "Monitor": 0, "Webcam": 4} with a threshold of 3 

Expected output: {"Mouse": 2, "Monitor": 0} 

Hint: Loop through both the keys and values with .items(). 

inventory = { 
    "Keyboard": 7, 
    "Mouse": 2, 
    "Monitor": 0, 
    "Webcam": 4 

 
threshold = 3 
 
low_stock = { 
    product: quantity 
    for product, quantity in inventory.items() 
    if quantity <= threshold 

 
print(low_stock) 
 

This dictionary comprehension filters the original inventory while preserving the relationship between each product and its quantity. 

Try next: Return separate lists for out-of-stock products and low-stock products. 

6. Filter and Transform Sensor Readings 

Task: Remove missing and out-of-range Celsius readings, then convert the valid values to Fahrenheit. 

Sample input: [18.5, None, 22.1, -5, 19.8, 101, 21.0] 

Expected output: [65.3, 71.8, 67.6, 69.8] 

Hint: Validate each reading before applying the conversion formula. 

readings = [18.5, None, 22.1, -5, 19.8, 101, 21.0] 
 
fahrenheit = [ 
    round((reading * 9 / 5) + 32, 1) 
    for reading in readings 
    if reading is not None and 0 <= reading <= 100 

 
print(fahrenheit) 
 

The condition runs before the calculation, so Python never attempts arithmetic with None. The exercise also shows why data validation should happen before transformation. 

Try next: Keep the rejected values in a separate list and attach a reason to each one. 

7. Build a Reusable Dataset Summary Function 

Task: Write a function that returns the count, minimum, maximum, and average of a numerical list. 

Sample input: [14, 18, 11, 20, 17] 

Expected output: {"count": 5, "minimum": 11, "maximum": 20, "average": 16.0} 

Hint: Handle an empty list before using min() or max(). 

def summarise(values): 
    if not values: 
        return { 
            "count": 0, 
            "minimum": None, 
            "maximum": None, 
            "average": None 
        } 
 
    return { 
        "count": len(values), 
        "minimum": min(values), 
        "maximum": max(values), 
        "average": round(sum(values) / len(values), 2) 
    } 
 
 
scores = [14, 18, 11, 20, 17] 
print(summarise(scores)) 
 

Placing the logic inside a function makes it reusable. Returning a dictionary also makes the meaning of each result clearer than returning several unlabelled values. 

Try next: Ignore None values safely instead of treating the entire input as invalid. 

8. Rank Challenge Participants 

Task: Rank participants by score from highest to lowest. When scores are equal, place the participant with the lower completion time first. 

participants = [ 
    {"name": "Riya", "score": 84, "time": 320}, 
    {"name": "Aman", "score": 91, "time": 410}, 
    {"name": "Neha", "score": 91, "time": 380}, 
    {"name": "Kabir", "score": 84, "time": 300} 

 

Expected order: Neha, Aman, Kabir, Riya 

Hint: Use a negative score for descending order and a positive time for ascending order. 

ranked = sorted( 
    participants, 
    key=lambda participant: (-participant["score"], participant["time"]) 

 
for rank, participant in enumerate(ranked, start=1): 
    print( 
        rank, 
        participant["name"], 
        participant["score"], 
        participant["time"] 
    ) 
 

The sorting key is a tuple. Python compares the score first and uses time only when two scores match. This pattern is useful for leaderboards and any data that requires multiple sorting rules. 

Try next: Give participants with the same score and time the same rank. 

9. Parse Records and Handle Invalid Values 

Task: Convert comma-separated participant records into dictionaries. Keep invalid records separately instead of allowing the program to stop. 

records = [ 
    "P001,Anaya,88", 
    "P002,Rohit,not_available", 
    "broken_record", 
    "P003,Meera,76" 

 

Expected result: Two valid records and two invalid records. 

Hint: Both unpacking and integer conversion can raise ValueError. 

valid_records = [] 
invalid_records = [] 
 
for record in records: 
    try: 
        participant_id, name, score_text = record.split(",") 
        score = int(score_text) 
 
        if not 0 <= score <= 100: 
            raise ValueError("Score is outside the allowed range") 
 
        valid_records.append({ 
            "id": participant_id, 
            "name": name, 
            "score": score 
        }) 
    except ValueError: 
        invalid_records.append(record) 
 
print("Valid:", valid_records) 
print("Invalid:", invalid_records) 
 

The try block handles records that have the wrong number of fields, a non-numeric score, or a score outside the accepted range. Separating invalid data makes the problem visible without losing valid results. 

Try next: Store a specific failure reason beside each rejected record. 

10. Build a Mini Data Quality Checker 

Task: Inspect a small dataset for duplicate IDs, missing names, and scores outside the range of 0 to 100. 

records = [ 
    {"id": 1, "name": "Asha", "score": 82}, 
    {"id": 2, "name": "", "score": 91}, 
    {"id": 2, "name": "Vikram", "score": 110}, 
    {"id": 4, "score": 76} 

 

Expected report: Duplicate ID 2, missing names in rows 2 and 4, and an invalid score in row 3. 

Hint: Use a set for IDs and a dictionary containing one list for each issue type. 

def check_data_quality(records): 
    seen_ids = set() 
    report = { 
        "duplicate_ids": [], 
        "missing_name_rows": [], 
        "invalid_score_rows": [] 
    } 
 
    for row_number, record in enumerate(records, start=1): 
        record_id = record.get("id") 
 
        if record_id in seen_ids: 
            report["duplicate_ids"].append(record_id) 
        else: 
            seen_ids.add(record_id) 
 
        name = record.get("name") 
        if not isinstance(name, str) or not name.strip(): 
            report["missing_name_rows"].append(row_number) 
 
        score = record.get("score") 
        if not isinstance(score, (int, float)) or not 0 <= score <= 100: 
            report["invalid_score_rows"].append(row_number) 
 
    return report 
 
 
print(check_data_quality(records)) 
 

This final problem combines loops, conditions, sets, dictionaries, functions, type checks, and defensive access with .get(). More importantly, it asks you to translate several validation rules into one clear report. 

Try next: Add checks for a missing ID and duplicate IDs that appear three or more times. 

Completing an exercise once is useful, but improvement becomes clearer when you can adapt your solution. After each problem, ask: 

  • Can I explain why every line is needed? 
  • Can I solve the same problem again without copying? 
  • What happens when the input is empty, missing, duplicated, or incorrectly formatted? 
  • Can I divide a larger requirement into smaller functions? 
  • Can I make the code clearer without changing its result? 

Do not judge progress only by speed. A slower solution that you understand and can test is more valuable than a fast solution you cannot explain. 

The next step is to solve unfamiliar problems where the expected approach is not already shown. CompeteX by PangaeaX offers structured Python and data challenges with AI evaluation and scoring, helping you apply your skills in a more challenging environment. 

As you build stronger projects and practical experience, AuthenX can help authenticate your capabilities through portfolio screening and an AI-led interview. If you need learning support or want to discuss your approach with other data professionals, you can also participate in the ConnectX community

Start with one exercise today, complete its extension, and then test what you can do when the solution is no longer provided. 

How much Python should I know before attempting these problems? 

You should understand variables, basic data types, conditions, loops, lists, dictionaries, and simple functions. You do not need knowledge of external libraries such as pandas or NumPy. 

How long should I spend on each Python exercise? 

There is no required time limit. Give yourself enough time to understand the requirement, attempt a solution, test it, and identify where you became stuck. Set a personal limit if you repeatedly spend time changing code without learning anything new. 

Should beginners use AI when solving Python problems? 

AI can help explain an error, create an additional test case, or review your reasoning. Try writing a first solution before requesting complete code. Otherwise, you may recognise the answer without developing the ability to produce it yourself. 

What should I practise after completing these ten problems? 

Repeat the exercises with different inputs, combine two problems into one program, and then attempt structured Python coding challenges. You can also progress into file handling, object-oriented programming, APIs, data analysis libraries, and testing as your fundamentals become more reliable. 

Stay Updated with PangaeaX

Subscribe to our newsletter for the latest insights, updates, and
opportunities in data science.