Common coding mistakes (and how to fix them)¶
Beginner-friendly · 15 min · every example runs
Most bugs aren't exotic — they're the same handful of mistakes, made again and again. Each one below shows ❌ the mistake (with the wrong result it really produces) and ✅ the fix.
Jump to: Python gotchas · Error handling · Performance · GenAI-specific · Security
Python gotchas¶
1. Using a list or dict as a default argument¶
The default value is created once, when the function is defined — so every call shares it.
2. Changing a list while looping over it¶
Removing items shifts the rest left, so the loop skips the next item.
3. "Copying" a list with =¶
= gives the same list a second name — changing one changes both.
import copy
base_messages = [{"role": "system", "content": "Be brief."}]
chat = copy.deepcopy(base_messages) # independent copy (also copies the dicts inside)
chat.append({"role": "user", "content": "Hi"})
print(len(base_messages)) # → 1
For a flat list of numbers or strings, items.copy() is enough.
4. Treating 0, "" or [] as "missing"¶
if not value is also true for 0, empty strings and empty lists — not just None.
5. Naming a variable list, dict, id, input or type¶
That hides Python's built-in of the same name for the rest of the file.
6. Functions created in a loop all "remember" the last value¶
A function looks up loop variables when it runs, not when it's created.
7. Comparing decimals with ==¶
Computers store most decimals approximately.
Error handling¶
8. Catching everything and hiding it¶
A bare except: (or except Exception: pass) hides real bugs — typos, wrong keys, network
outages — and leaves you guessing.
9. Opening files without encoding="utf-8"¶
On Windows the default encoding isn't UTF-8, so files with ₹, emoji or Hindi text break —
sometimes only on a colleague's machine.
Performance¶
10. Building a long string with += in a loop¶
Each += creates a whole new string — slow for big documents.
11. Checking membership in a big list¶
x in some_list scans every item; x in some_set is near-instant.
GenAI-specific¶
12. Trusting the model's JSON without checking it¶
Models sometimes add text around the JSON, miss a field, or use the wrong type.
from pydantic import BaseModel, Field, ValidationError
class Ticket(BaseModel):
priority: int = Field(ge=1, le=5) # the shape you expect, enforced
try:
ticket = Ticket.model_validate_json('{"priority": "high"}')
except ValidationError as err:
print("Invalid model output:", err.error_count(), "problem") # → Invalid model output: 1 problem
# …retry the request, including the error message so the model can fix it
More in Type hints, dataclasses & Pydantic.
13. No timeout or retries on API calls¶
Networks fail and APIs rate-limit. Without a timeout, one hung request freezes your app.
14. Blocking the event loop in async code¶
time.sleep() or requests.get() inside async def freezes every other task.
import asyncio
async def call_model():
await asyncio.sleep(0.1) # lets other tasks run while this one waits
return "reply"
print(asyncio.run(call_model())) # → reply
Use async libraries inside async def — httpx.AsyncClient, AsyncOpenAI. See Async programming.
15. Sending far too much text to the model¶
Pasting whole documents into every prompt is slow and expensive — and often gives worse answers, because the important part gets lost.
- ✅ Retrieve only the relevant chunks (that's what RAG is for).
- ✅ Summarise long chat histories instead of resending everything.
- ✅ Log token counts per request so you notice when a prompt suddenly grows.
Security¶
16. Putting API keys in your code¶
Keys in code end up in Git history, screenshots and shared notebooks — and leaked keys get abused within minutes.
Also: don't log secrets or personal data
Logging full prompts can store customers' names, emails or keys in plain text. Log IDs, sizes and timings instead — or redact before logging.
A debugging checklist¶
When something's wrong, check these first:
- Read the whole error message — the last line says what, the lines above say where.
- Print (or log) the actual value and its
type()just before the failing line. - Is a value
Nonewhen you expected something? - Did a list or dict change somewhere you didn't expect (mistakes 1–3)?
- Are you in the right virtual environment (
which python/where python)? - For LLM bugs: log the exact prompt and the raw reply.