10 Common Python Mistakes and How to Avoid Them
This article lists ten frequent Python pitfalls—including mutable default arguments, class variable misuse, incorrect exception handling, scope errors, list mutation during iteration, closure binding issues, circular imports, module name conflicts, Python 2/3 incompatibilities, and improper __del__ usage—explaining each problem with examples and providing clear solutions.
Python is a simple yet powerful language, but developers often fall into subtle traps that can cause bugs or unexpected behavior. This guide enumerates ten of the most common mistakes and shows how to fix them.
1. Using mutable objects as default argument values
def foo(bar=[]):
bar.append("baz")
return bar
>>> foo()
["baz"]
>>> foo()
["baz", "baz"]Solution: use None as the default and create a new list inside the function.
def foo(bar=None):
if bar is None:
bar = []
bar.append("baz")
return bar2. Misusing class variables
class A(object):
x = 1
class B(A):
pass
class C(A):
pass
print(A.x, B.x, C.x) # 1 1 1
B.x = 2
print(A.x, B.x, C.x) # 1 2 1
A.x = 3
print(A.x, B.x, C.x) # 3 2 3Class attributes are shared via the inheritance chain; modifying them on a subclass does not affect the base class.
3. Incorrect exception specification
try:
l = ["a", "b"]
int(l[2])
except ValueError, IndexError:
passIn Python 2 the comma syntax is for binding the exception, not for catching multiple types. Use a tuple and as :
except (ValueError, IndexError) as e:
pass4. Misunderstanding scope (LEGB)
x = 10
def foo():
x += 1
print(x)
foo()
# UnboundLocalErrorAssigning to a variable makes it local; use global or nonlocal if needed.
5. Deleting items while iterating a list
odd = lambda x: bool(x % 2)
numbers = [n for n in range(10)]
for i in range(len(numbers)):
if odd(numbers[i]):
del numbers[i]Fix by building a new list or iterating over a copy:
numbers = [n for n in numbers if not odd(n)]6. Closure variable binding
def create_multipliers():
return [lambda x: i * x for i in range(5)]
for m in create_multipliers():
print(m(2))
# prints 8 five timesCapture the current value with a default argument:
def create_multipliers():
return [lambda x, i=i: i * x for i in range(5)]7. Circular import problems
# a.py
import b
def f():
return b.x
print(f())
# b.py
import a
x = 1
def g():
print(a.f())Import inside functions to break the cycle.
8. Naming conflicts with standard library modules
A user‑defined email.py can shadow the built‑in email package, leading to import errors.
9. Python 2 vs Python 3 exception handling
def bad():
e = None
try:
bar(int(sys.argv[1]))
except KeyError as e:
print('key error')
except ValueError as e:
print('value error')
print(e)In Python 3 the variable e is not assigned if the exception is caught, causing UnboundLocalError . Assign to a separate variable inside each except block.
10. Misusing the __del__ method
class Bar(object):
def __del__(self):
foo.cleanup(self.myhandle)During interpreter shutdown module globals may be None . Prefer atexit.register() for cleanup.
Understanding these nuances helps Python developers write more reliable and maintainable code.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.