Common Python Pitfalls and How to Avoid Them
This article surveys typical Python traps—including UnboundLocalError, mutable default arguments, in‑place versus out‑of‑place updates, tuple syntax, shared mutable containers, list mutation during iteration, closure late binding, __del__ pitfalls, import inconsistencies, version differences, operator quirks, attribute magic methods, and the GIL—explaining why they occur and offering safe alternatives.
The author defines a "trap" as code that appears to work but behaves unexpectedly, distinguishing it from outright errors that raise exceptions.
1 Mutable objects as default arguments
Using a mutable object (e.g., a list) as a default parameter causes the same object to be shared across calls, leading to surprising accumulation of state.
<code>>> def f(lst = []):
... lst.append(1)
... return lst
>>> f()
[1]
>>> f()
[1, 1]</code>The fix is to use None as the default and create a new object inside the function.
<code>>> def report(when=None):
... if when is None:
... when = time.time()
... return when
>>> report()
1500113446.746997
>>> report()
1500113448.552873</code>2 x += y vs x = x + y
While both forms often yield the same result, += modifies the object in place (preserving its identity), whereas x = x + y creates a new object.
<code>>> x=[1]; print id(x); x=x+[2]; print id(x)
4357132800
4357132728
>>> x=[1]; print id(x); x+=[2]; print id(x)
4357132800
4357132800</code>3 Parentheses – creating tuples
Parentheses denote a tuple, which is immutable. A single element requires a trailing comma to be recognized as a tuple.
<code>>> a = (1,)
>>> type(a)
<class 'tuple'>
>>> a = (1)
>>> type(a)
<class 'int'>
</code>4 Generating a list of lists
Using the multiplication operator on a mutable list creates multiple references to the same inner list, causing unintended shared mutations.
<code>>> a = [[]] * 10
>>> a[0].append(10)
>>> a
[[10], [10], [10], [10], [10], [10], [10], [10], [10], [10]]</code>The correct approach is a list comprehension:
<code>>> a = [[] for _ in range(10)]
>>> a[0].append(10)
>>> a
[[10], [], [], [], [], [], [], [], [], []]
</code>5 Modifying a list while iterating
Deleting elements from a list during iteration can skip items because the index continues to increase while the list shrinks.
<code>>> def modify_lst(lst):
... for idx, elem in enumerate(lst):
... if elem % 3 == 0:
... del lst[idx]
>>> lst = [1,2,3,4,5,6]
>>> modify_lst(lst)
>>> lst
[1, 2, 4, 5]
</code>A safer alternative is to build a new list with a comprehension.
6 Closures and lambda late binding
Lambda functions inside a loop capture the loop variable by reference, so all generated functions see the final value of the variable.
<code>>> def create_multipliers():
... return [lambda x: i*x for i in range(5)]
>>> for m in create_multipliers():
... print m(2)
8
8
8
8
8
</code>Fix by binding the current value as a default argument:
<code>>> def create_multipliers():
... return [lambda x, i=i: i*x for i in range(5)]
</code>7 Defining __del__
Objects with a __del__ method can break Python's cyclic‑garbage collector, potentially causing memory leaks.
8 Different import styles for the same module
Importing a module inside functions using different syntaxes can create distinct module objects (different id values), leading to state inconsistencies.
9 Python version upgrades
Python 3 changes the return types of range , map , filter , and dict.items from lists to iterators, which can affect code that expects a list.
10 ++i — i
In Python, the expression ++i - i leaves i unchanged because the double plus is interpreted as two unary plus operators.
11 setattr, getattr, __getattribute__
These magic methods control attribute access; getattr is only invoked when normal lookup fails, while __setattr__ and __getattribute__ handle all attribute assignments and retrievals.
12 GIL
The Global Interpreter Lock is a well‑known limitation of CPython that prevents true parallel execution of Python bytecode in multiple native threads.
Conclusion
Python is easy to learn and powerful, but being aware of these common pitfalls helps 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.