5 Python mistakes every beginner makes (and how to fix them in 2026)
Most Python beginners hit the same five walls. Once you know they're coming, you avoid them entirely. Here they are, with the fix for each.
Mistake 1: Mutable default arguments
The trap:
\\\`python
def add_item(item, items=[]):
items.append(item)
return items
print(add_item("a")) # ["a"]
print(add_item("b")) # ["a", "b"] ← surprise!
\\\`
The list default is created once at function definition time, not each call. Every call mutates the same list.
The fix:
\\\`python
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
\\\`
Rule: never use mutable objects (\[]\, \{}\, \set()\) as default arguments. Use \None\ and create them inside the function.
Mistake 2: Confusing copy and reference
The trap:
\\\`python
a = [1, 2, 3]
b = a # b is the SAME list, not a copy
b.append(4)
print(a) # [1, 2, 3, 4] ← oops
\\\`
The fix:
\\\`python
b = a.copy() # shallow copy
OR
b = list(a) # also shallow copy
OR
import copy
b = copy.deepcopy(a) # full deep copy (for nested structures)
\\\`
For nested structures (lists of lists, dicts of lists), \.copy()\ is not enough. You need \copy.deepcopy()\.
Mistake 3: Using \==\ instead of \is\ (or vice versa)
The trap:
\\\`python
x = None
if x == None: # works but un-Pythonic
...
if a == b: # value equality
...
if a is b: # identity (same object in memory)
...
\\\`
The fix: use \is\ for None, True, False. Use \==\ for everything else.
\\\`python
if x is None: # correct
if value == 42: # correct
if name == "Ada": # correct
\\\`
\is\ checks memory identity. \==\ checks logical equality. \x is 0\ happens to work in current CPython for small ints (interned), but you're relying on an implementation detail. Don't.
Mistake 4: Mixing \for i in range(len(items))\ with iteration
The trap (un-Pythonic):
\\\`python
for i in range(len(items)):
print(items[i])
\\\`
The fix (Pythonic):
\\\`python
for item in items:
print(item)
If you need the index too:
for i, item in enumerate(items):
print(i, item)
\\\`
\enumerate\ exists exactly so you don't need \range(len(...))\. The Pythonic version is also faster and clearer.
Mistake 5: Catching all exceptions silently
The trap:
\\\`python
try:
do_something()
except:
pass # ← swallows EVERY error, including KeyboardInterrupt and bugs
\\\`
The fix:
\\\`python
try:
do_something()
except ValueError as e:
log.warning("bad input: %s", e)
\\\`
Rule: catch the specific exception you expect. If you must catch everything, at least log it. Bare \except: pass\ is the #1 reason beginner code has invisible bugs that show up six months later in production.
Bonus: forgetting that strings are immutable
\\\`python
s = "hello"
s[0] = "H" # TypeError — strings can't be modified in place
\\\`
The fix:
\\\`python
s = "H" + s[1:] # or
s = s.replace("h", "H", 1)
\\\`
This catches almost every beginner the first time they try to modify a string. Strings are immutable. You create a new one.
How to internalize these
Reading is not enough. Open a Python REPL (or our interactive lessons) and reproduce each trap. Run the broken code, see the bug, write the fix, run it again. That muscle memory is what makes you actually avoid these in your own code.
Our Common Mistakes track covers all five of these plus 15 more in interactive, runnable form — with an AI tutor that explains why each one breaks.