As new programmers, we’ve all made mistakes. But some mistakes are bound to happen due to not knowing the nature of a programming language. So I’ve compiled some of the most common mistakes you might make while programming in Python.
6Modifying a List While Iterating
Modifying aPython listwhile you’re looping through it might sound like a clever shortcut, but it’s a classic Python gotcha! This sneaky mistake can lead to unexpected behavior, like skipping elements or ending up with a completely messed-up list.
Let’s say we have a list of numbers, and we want to remove all numbers less than 5. Sounds straightforward, right?

If you run this code, you’ll find that the number 2 remains on the list.
But why? In this code, we’re trying to iterate throughnumbersand remove elements that are less than 5. However, when we remove an element, the list shrinks, and the indices of the subsequent elements shift.

This can cause the loop to skip over elements. For example, when1is removed,2moves into1’s old position, but the loop’s internal counter has already moved on, potentially skipping2.
The safest and most common way to modify a list based on its elements is to iterate over a copy of the list or to build a new list with only the elements you want to keep. In the copy approach, we create a shallow copy of the list before iterating. This way, you may remove elements from the original list without affecting the iteration process.

By usingnumbers[:], we create asliceof thenumberslist, which is a shallow copy. Theforloop then iterates over this copy, completely independent of any modifications we make to the originalnumberslist.
Often, a morePythonic wayto achieve this is to create a new list containing only the items you want to keep. This approach avoids in-place modification altogether and is often more efficient.

In this code, we use list comprehension to create a new list from the original one that contains our desired elements. This also keeps the original list intact.
5Naming Conflicts
Choosing variable and file names might seem like a small detail until Python turns around and bites you (figuratively.) Naming things poorly can lead to weird bugs, shadowed functionality, and hours of confusion. There are two common ways this happens: using Python keywords or built-in names as your own, and accidentally naming your scripts after existing Python modules.
Python won’t stop you from naming a variablelist,str, or evensum. But just because you can, doesn’t mean you should.
This code will run without any issues. However, if you add another line that contains thelist()function in Python, you get an error.
That’s because you’ve overwritten the built-inlist()function with your own list object. When you try to calllist(‘123’), Python thinks you’re trying to call your own list, not the built-in function. So, always use descriptive names that don’t clash with Python’s core features.
Not only will this help you avoid using reserved keywords, but it’s also good practice for code readability and debugging. The same goes for naming your script files. Let’s say you create a file namedrandom.pyto experiment with random numbers:
But when you run this, you’ll likely see an error complaining that “module ‘random’ has no attribute ‘randint’.” Python is importing your own file (random.py) instead of the actualrandommodule from the standard library. Classic shadowing bug.
Avoid naming your scripts after existing modules likerandom.py,math.py,os.py, orjson.py. And if you accidentally do it, don’t forget to delete the corresponding.pycor__pycache__folders after renaming.
4Mutable Function Arguments
Python lets you set default values for function arguments, which is super convenient. But when those default values are mutable (like lists or dictionaries), you’re walking into a sneaky bug trap.
The default mutable object is created only once, when the function is defined, not each time it’s called. That means if it gets modified, that change sticks around for the next call.
When you run this code, you might expect each call toadd_item_to_list()to start with a fresh, empty list if you don’t provide one. However, the output will show something unexpected:
We called the function twice. So why is"apple"still there on the second call? The listitem_listis only created once, so every call to the function keeps modifying the same list. This leads to surprising and very buggy behavior. To fix this, you can useNoneas the default and create the list inside the function:
By defaulting toNone, a new list is created every time the function is called.
3Handling Files the Wrong Way
Working with files in Python is pretty easy. But there’s a common mistake that can sneak into your code. Not closing the file. It might seem harmless, but leaving files open can lead to memory leaks, file corruption, or locked files that can’t be accessed by other programs.
Leaving files open can cause serious trouble. It can even prevent the file from being deleted or modified by other processes. That’s why you should always make sure to close the file after you finish your operations. You can do so using theclose()function.
Another best practice is to use Python’swithstatement, which automatically takes care of closing the file for you.
Thewithblock handles all the behind-the-scenes cleanup. As soon as you exit the block, Python closes the file for you. This allows you not to worry about manually closing the file yourself.
2Importing Everything From a Module
As a beginner, it’s tempting to just slap afrom module import *at the top of your script and call it a day. But as your code grows, this shortcut becomes a recipe for disaster.
What if bothmathandcustom_mathdefine a function calledsqrt()? Which one gets called? Python doesn’t tell you. It just silently overrides the earlier one.
You could be using a completely different function without realizing it. Moreover, in large codebases, debugging becomes a nightmare in large codebases. You lose track of where functions or classes are coming from. That’s why you should be explicit with your imports.
Or even like this:
Explicit is better than implicit (a core idea fromthe Zen of Python.) You always know what you’re using and where it came from.
1Proper Exception Handling
Even the most carefully crafted code can run into unexpected problems. These are called exceptions in Python. Handling them gracefully is what makes your program robust. However, many beginners approach exception handling with a “catch-all” mentality, using broadexceptclauses. It might silence the error for now, but it leaves your code fragile, confusing, and hard to debug.
This catches everything. Even errors you didn’t expect or want to handle. Syntax errors, keyboard interrupts, typos, broken imports. Python will swallow them all with that genericexcept. This isn’t ideal. Instead, be specific about what you’re catching:
You’re catching only the error you expect. If something else goes wrong, Python will still raise it. So you won’t silently ignore real bugs. You can also handle multiple exceptions smartly:
Avoidexcept:by itself. If you must catch all exceptions (rarely), useexcept Exception:and still handle it carefully. By handling exceptions specifically, your code becomes more predictable, easier to debug, and capable of providing more meaningful feedback.
By avoiding these mistakes, you’ll introduce fewer errors, which means lessdebugging of your Python code. If you’re new to Python and looking for some resources, there are manygames that teach Python. Other than that, you can also do projects like anexpense trackeror createbasic scripts.