Code Review · Python

Python Code Review: Mutable Class Variable

Review a Python class that accidentally shares a list across all instances.

Code Review Exercise

Review the following class. The code looks small, but it contains a common Python bug that can leak state between separate objects.

python
class ShoppingCart:
    items = []

    def add_item(self, item):
        self.items.append(item)

    def get_items(self):
        return self.items


cart_a = ShoppingCart()
cart_b = ShoppingCart()

cart_a.add_item("apple")

print(cart_b.get_items())  # What prints here?

What issues do you see before scrolling further?

Review Findings

Issue #1: items is a class variable, not an instance variable

items = [] is defined on the class. That means the list is shared by all ShoppingCart instances unless an instance overrides it.

Issue #2: State leaks between objects

Adding "apple" to cart_a also affects what cart_b.get_items() returns, because both objects are using the same underlying list.

Issue #3: The bug is easy to miss in small tests

If a test only creates one cart, the code may appear to work. The bug becomes visible when multiple instances are created in the same process.

Issue #4: Returning the internal list exposes mutable state

get_items() returns the actual list. Callers can modify the cart without using add_item(), which makes the class harder to reason about.

Why This Happens

In Python, variables assigned directly inside the class body are class attributes. They are shared by all instances.

This is sometimes useful for constants, but dangerous for mutable values like lists, dictionaries, and sets when each object is expected to have its own independent state.

Fixed Version

python
class ShoppingCart:
    def __init__(self):
        self.items = []

    def add_item(self, item):
        self.items.append(item)

    def get_items(self):
        return list(self.items)

Now each ShoppingCart gets its own list when the object is created. Returning list(self.items) gives callers a copy instead of the internal list.

When Class Variables Are Fine

Class variables are not always bad. They are useful for values that are intentionally shared across all instances.

python
class ShoppingCart:
    MAX_ITEMS = 100

    def __init__(self):
        self.items = []

A constant like MAX_ITEMS is a good class variable. A per-cart list of items should be an instance variable.

Interview Follow-Ups

Is this the same as mutable default arguments?

It is related, but not identical. Both bugs come from mutable state being created once and reused unexpectedly. Mutable default arguments happen at function definition time. Mutable class variables are shared at the class level.

Are all class variables bad?

No. Class variables are fine for constants or intentionally shared state. The problem is using a mutable class variable when each instance should have its own value.

Why return a copy from get_items()?

Returning the internal list lets callers mutate the object's state directly. Returning a copy protects the object's internal representation.

What should a reviewer say in an interview?

Mention that items is shared across all instances, move it into __init__, and consider returning a copy to avoid exposing mutable internal state.

What Interviewers Expect

A strong reviewer should catch that items is shared across instances and explain why that is surprising.

A senior-level answer goes one step further and mentions object ownership: each cart should own its own items, and callers should not be able to mutate internal state accidentally.