Fundamentals 9 min read

Common Python Pitfalls: Dynamic Typing, Mutable Default Arguments, Scope, and List Modification

This article examines several confusing behaviors in Python—including implicit variable declarations, mutable default arguments, class variable inheritance, scope rules, and list‑modification during iteration—illustrating each with code examples and offering practical solutions for developers.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Common Python Pitfalls: Dynamic Typing, Mutable Default Arguments, Scope, and List Modification

Python has become the most popular language for data science and AI, but it still contains many confusing behaviors that can trip up both beginners and experienced developers.

Because Python is dynamically typed, variables are created without explicit type declarations, which can lead to runtime crashes when a variable’s type is not what the code expects.

Mutable default arguments are a classic source of bugs; the function def add_five(a, b=0): return a + b + 5 works as expected, but using a mutable object like a list as a default value causes the list to retain items across calls, as shown by the add_element examples that unexpectedly return ["foo", "foo"] on the second call.

<code>def add_five(a, b=0):
    return a + b + 5</code>
<code>add_five(3)   # returns 8
add_five(3, 4)   # returns 12</code>
<code>def add_element(lst=[]):
    lst.append("foo")
    return lst

add_element()   # returns ["foo"]
add_element()   # returns ["foo", "foo"]  # unexpected</code>

Class variables are shared across all instances unless overridden; modifying a subclass’s attribute does not affect the parent, but changing the parent’s attribute propagates to subclasses, which can be surprising.

<code>class Parent(object):
    x = 1
class FirstChild(Parent):
    pass
class SecondChild(Parent):
    pass
print(Parent.x, FirstChild.x, SecondChild.x)   # 1 1 1

FirstChild.x = 2
print(Parent.x, FirstChild.x, SecondChild.x)   # 1 2 1

Parent.x = 3
print(Parent.x, FirstChild.x, SecondChild.x)   # 3 2 3</code>

Scope rules can also be confusing: a variable defined inside a function is not accessible outside, and attempting to modify a global variable without the global keyword raises UnboundLocalError . Declaring the variable as global resolves the issue.

<code>x = 2

def add_5():
    global x
    x = x + 5
    print(x)

add_5()   # works, prints 7</code>

Modifying a list while iterating over it leads to index errors; a safer approach is to use a list comprehension that filters out unwanted elements in a single expression.

<code>mynumbers = [x for x in range(10) if x % 3 != 0]
# Result: [1, 2, 4, 5, 7, 8]</code>

Although Python’s execution speed has historically been slower than compiled languages, modern libraries such as NumPy, and multi‑core processing, as well as the rise of machine‑learning frameworks like PyTorch and TensorFlow, have mitigated many performance concerns. Nonetheless, developers should remain aware of these language quirks when writing robust Python code.

Pythonlist comprehensionclass-variablesDynamic TypingScopemutable default arguments
Python Programming Learning Circle
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.