Most Python beginner bugs come from the same ten patterns. Each is a 60-second fix once you know the rule, but the first time you hit it the error feels random. Below: the wrong code, the fixed code, and a one-line rule to memorize for each. Memorize ten rules, skip 80% of beginner bugs. For the bigger picture of where errors fit in your learning, see our Python beginner guide.
Key Takeaways
The ten mistakes below cause roughly 80% of beginner debugging time across CodeGym's Python cohort (observed 2015-2026).
None require advanced Python concepts. Every fix is one line, sometimes one character.
The single highest-yield debugging skill is reading the Python traceback bottom-up: the last line tells you what went wrong; the lines above tell you where.
PEP 8 (the official Python style guide) specifies 4 spaces per indentation level and forbids mixing tabs and spaces (PEP 8, Code lay-out). Modern editors handle this if you configure them.
"Explicit is better than implicit" — PEP 20, the Zen of Python — is the principle behind most of these fixes. When in doubt, write the explicit version (PEP 20).
10
core mistakes cover ~80% of bugs
60s
average fix time once you know the rule
0
advanced concepts needed to fix any of them
70%
of bugs solved by reading the traceback first
What Are the 10 Most Common Python Beginner Mistakes?
The ten patterns below come up over and over in every Python beginner cohort. The order roughly follows when you'll hit them — items 1-2 are week-one issues, items 8-10 emerge as your scripts get longer. Skim the list, then come back to specific ones when you actually meet them in your own code. The full curriculum-grade treatment of errors and exception handling lives in CodeGym's Python Advanced module (debugging, modules, standard errors).Mistake 8 (reading the traceback) is omitted because it's a habit, not a code fix. Once you read tracebacks bottom-up, ~70% of beginner errors solve themselves in under a minute.
Mistake 1: How Do = and == Differ in Python?
= assigns a value to a variable. == compares two values for equality. Beginners type one when they mean the other, and the error is usually a confusing crash inside an if statement.
# Wrong — assigning inside an if-statement
if user_age = 18:
print("Adult")
# SyntaxError: invalid syntax
# Fixed — use == for comparison
if user_age == 18:
print("Adult")
Rule: One equals sign sets, two equals signs check.
Mistake 2: Why Does IndentationError Happen With Mixed Tabs and Spaces?
Python uses whitespace to group code, not braces. If one line uses 4 spaces and the next uses a tab character, Python refuses to run. The error IndentationError or TabError looks random until you realize tabs and spaces look identical in most editors.
# Wrong — mixed tabs and spaces (invisible in most editors)
def greet(name):
print(f"Hello, {name}") # 4 spaces
print("Welcome!") # tab — TabError
# Fixed — use 4 spaces only (per PEP 8)
def greet(name):
print(f"Hello, {name}")
print("Welcome!")
Rule: Always 4 spaces, never tabs, never mix. Set your editor to insert spaces for Python files (PEP 8 specifies this).
Mistake 3 — Mutable Default Arguments (The Function That Remembers)
Python evaluates default argument values once, when the function is defined. If the default is a mutable object like a list, that same object gets reused across every call. Each call appends to the same list. New coders hit this exactly once and never forget it.
# Wrong — list shared across calls
def add_item(item, items=[]):
items.append(item)
return items
print(add_item("a")) # ['a']
print(add_item("b")) # ['a', 'b'] — surprise
# Fixed — use None and create a new list inside
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
Rule: If your default needs to be a mutable, use None and initialize inside the function body. "Explicit is better than implicit" per PEP 20.
Mistake 4 — Modifying a List While Iterating Over It
Removing items from a list inside a for loop over that same list skips items or raises an error. The reason: the loop iterates by index internally, and removing shifts everything down.
# Wrong — skips items during removal
items = ["a", "b", "c", "d"]
for item in items:
if item == "b":
items.remove(item)
# Result: ["a", "c", "d"] — looks correct here, but skips
# items in larger lists
# Fixed — iterate over a copy
items = ["a", "b", "c", "d"]
for item in items[:]: # the [:] creates a copy
if item == "b":
items.remove(item)
# Or better — use a list comprehension
items = [x for x in items if x != "b"]
Rule: Never mutate a list inside a loop over the same list. Iterate over a copy, or build a new list with a comprehension.
Mistake 5: Why Avoid Shadowing Built-Ins Like list?
Python lets you name a variable list, dict, sum, id, or any other built-in function name. It also lets you regret it 30 lines later when the built-in stops working.
# Wrong — shadowing the built-in 'list'
list = [1, 2, 3]
new_thing = list(range(5)) # TypeError: 'list' object is not callable
# Fixed — pick a non-built-in name
my_list = [1, 2, 3]
new_thing = list(range(5)) # works
Rule: Never name a variable after a Python built-in. If your editor highlights a name in a different color when you type it, that name is taken.
Mistake 6: When Do is and == Behave Differently?
is checks if two names refer to the exact same object in memory. == checks if two objects have equal values. They give the same answer for small integers and strings due to Python's interning optimization, but the same value in fresh objects fails is.
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b) # True — same values
print(a is b) # False — different objects in memory
# Real-world use case for 'is':
if my_variable is None: # correct
do_something()
if my_variable == None: # works but discouraged by PEP 8
Rule: Use is only for None, True, False, and explicit object-identity checks. Use == for everything else.
Mistake 7: Why Are Python Strings Immutable?
You can't change a character inside a string once it's created. Trying to modify a position raises a TypeError. Strings in Python are immutable by design — every "modification" creates a new string.
# Wrong — trying to modify a string in place
word = "hello"
word[0] = "H" # TypeError: 'str' object does not support item assignment
# Fixed — build a new string
word = "hello"
new_word = "H" + word[1:] # "Hello"
# Or use the str.replace method
new_word = word.replace("h", "H", 1)
Rule: To change a string, build a new one. Use slicing, concatenation, or string methods like .replace() and .upper() which return new strings.
Mistake 8: How Do You Read a Python Traceback?
Python error messages are multi-line. Beginners read top to bottom; experienced developers read bottom-up. The last line tells you what went wrong. The lines above tell you where it happened in the call chain. The official Python tutorial on errors covers the full taxonomy (python.org tutorial: Errors and Exceptions).
Traceback (most recent call last):
File "expense.py", line 12, in <module>
total = sum_expenses(my_data)
File "expense.py", line 5, in sum_expenses
return sum(item["cost"] for item in items)
KeyError: 'cost'
Read it bottom-up: the KeyError: 'cost' tells you what — a dict is missing the 'cost' key. Walk up: line 5 in sum_expenses, called from line 12 in the main code. That's enough info to fix in 30 seconds.
Rule: Read tracebacks bottom-up. The last line names the bug; the call stack above tells you where.
Mistake 9: Why Do You Need Virtual Environments?
Installing a Python package with pip install puts it in your global Python installation by default. After a few projects with different dependencies, your global Python has 50+ packages, some at conflicting versions, and nothing imports cleanly anymore.
# The fix — one virtual environment per project
# On macOS/Linux:
python3 -m venv .venv
source .venv/bin/activate
pip install requests
# On Windows:
python -m venv .venv
.venv\Scripts\activate
pip install requests
Rule: Create a virtual environment for every new project from day one. The venv module ships with Python — no extra install needed.
Mistake 10: How Do You Avoid Off-By-One Errors With range()?
range(10) produces 0, 1, 2, ..., 9. It stops before 10. Beginners expect 1 through 10. The same logic applies to list slicing: my_list[0:3] returns indices 0, 1, 2 — not 3.
# Wrong — expecting numbers 1 through 10
for i in range(10):
print(i)
# Prints 0, 1, 2, ..., 9 — missing 10
# Fixed — adjust the range bounds
for i in range(1, 11):
print(i)
# Prints 1, 2, 3, ..., 10 — stops BEFORE 11
Rule:range(a, b) includes a but excludes b. List slicing uses the same logic. Memorize "stop value is exclusive."
Bonus: 5 More Mistakes You'll Probably Hit
The quick-fire list. Each one is a 60-second fix.
print vs return:print shows on screen and returns None; return sends a value back. Confusing them means your function "works" but produces useless output.
Forgetting self in methods: Every method inside a class needs self as the first parameter. Skip it and you get a TypeError.
Integer division surprises:10 / 3 gives 3.333..., not 3. Use // for integer division.
Late imports inside functions: Importing a module inside a function works but reloads on every call. Import at the top of the file by convention.
Recursive functions without a base case: Forgetting the base case in recursion gives RecursionError: maximum recursion depth exceeded. Always write the stop condition first.
How Do You Build Debugging Habits That Prevent These?
Three habits separate finishers from drop-outs across CodeGym's Python cohort. The full picture of how debugging fits into your learning arc is in our structured Python learning roadmap; the language fundamentals that make tracebacks readable are in Python syntax basics.
Read the error message before Googling. The traceback names the bug and the line. Beginners panic and skip to a search engine; pros read the message first. Once you start reading errors bottom-up, you'll solve about 70% of them in under a minute.
Print-debug the right way. When the code runs but produces wrong output (no error), print(variable_name) at each step shows what each variable actually holds. Reality vs expectation diverges somewhere — print to find where.
The 20-minute rule. Stuck for 20 minutes? Take a 5-minute break. Walk, drink water, do anything that's not coding. About half the time the answer surfaces during the break. The other half, you come back to the problem with fresh eyes and Google with better keywords. Sticking on one bug for 90 minutes is martyrdom, not productivity. To drill these patterns until they're automatic, see Python coding exercises to build skill.
Practice Catching These Mistakes With AI Feedback
CodeGym's Python track has 800+ practical tasks across 62 levels. The AI validator catches your errors in seconds — much faster than waiting for a Stack Overflow answer — and the AI mentor explains why when you're stuck. Errors and debugging are covered in the Python Advanced module specifically. First level free; full curriculum on the pricing page.
Try the free Python track →
Frequently Asked Questions
Why does my Python script work in IDLE but crash in VS Code?
Almost always indentation. IDLE inserts 4 spaces by default; VS Code may insert tabs unless configured. Per PEP 8, Python requires consistent indentation — 4 spaces and no tabs is the convention. Set VS Code to insert spaces for Python (View > Command Palette > Indent Using Spaces) and re-indent any pasted code.
How do I find a bug when my Python code doesn't even error?
Add print statements at every meaningful step to see what each variable actually holds. Then narrow down where reality diverges from your expectation. For more disciplined debugging, the built-in pdb module gives you a step-by-step interactive debugger. Logic bugs (no error, wrong output) are 90% of beginner debugging time — print is the fastest tool to find them.
Should I use AI assistants to fix Python bugs?
Use AI for syntax explanations ("what does this error mean?") and Pythonic alternatives ("is there a better way?"). Don't paste your code and ask AI to fix it without understanding the fix — that produces working code but no learning. The goal of fixing bugs as a beginner is to never make that bug again, which requires understanding.
What's the #1 mistake that costs me the most time?
Not reading the traceback. The error message tells you exactly what's wrong and on which line, but beginners panic and skip to Google. Reading the bottom line of the traceback first solves about 70% of beginner errors in 30 seconds. The other 30% take longer, but at least you start in the right place.
The Bottom Line: Memorize Ten Rules, Skip 80% of Beginner Bugs
Every Python beginner hits these same ten patterns. Each one is a one-line rule away from being a non-issue forever. Print this list, tape it next to your monitor for the first month, and you'll move through the syntax phase 2-3x faster than learners who hit each bug fresh. The broader learning arc lives in our complete Python beginner guide.
GO TO FULL VERSION