← Back to list

How I Broke My Code Without Touching the Logic

Learn how Python lists can cause hidden bugs through references, shallow copies, sorting mistakes, and unsafe iteration.

Sanket Parmar in CodeToDeploy · 2026-06-04 16:06 · 56 claps · 4.6 min read
#python #debugging #python-list
Open on Medium ↗
Wiki topics: 💻 · Programming

How I Broke My Code Without Touching the Logic

Photo by LATIKA SARKER on Unsplash

Photo by LATIKA SARKER on Unsplash

The code looked fine. The logic was the same. Nothing had changed, at least nothing that I could see. But the output was wrong, and it stayed wrong no matter how many times I ran it.

🚨 HIRING: Tech Talent 💰 $50–$120/hr | 🔥 Multiple Roles

Frontend • Backend • Full Stack • Mobile • AI/ML • DevOps 👉 **Apply Here**

I’ve been there more than once. And almost every time, the problem traced back to Python lists behaving in ways I didn’t expect. No bugs in Python. Bugs in my assumptions about how lists work.

If you’ve spent an afternoon staring at code thinking it will work and then didn’t, this article might save your next one.

When You Change a List You Didn’t Mean to Touch

This one gets developers at every experience level. Python lists are mutable objects. When you assign a list to a new variable, you don’t get a copy, you get a second reference to the same list.

original = [1, 2, 3]
copy = original
copy.append(4)
print(original)  # [1, 2, 3, 4]

You touched copy. But original changed too. Both variables point to the same object in memory. This is not a bug, it's how Python works. But if you don't know it, it looks like magic, and not the good kind.

The fix is straightforward. Use original[:] or original.copy() when you need an actual separate list.

copy = original.copy()
copy.append(4)
print(original)  # [1, 2, 3]
print(copy)      # [1, 2, 3, 4]

This behavior gets even more dangerous with nested lists. A shallow copy duplicates the outer list but still shares references to any inner lists. For nested structures, you need copy.deepcopy().

Modifying a List While You Loop Through It

This one is subtle and the results are unpredictable. When you remove items from a list while iterating over it, Python doesn’t stop and recalculate. It keeps moving the index forward, but the list underneath is shrinking. Items get skipped. No error is raised. The code runs, produces wrong output, and you have no idea why.

numbers = [1, 2, 3, 4, 5, 6]
for num in numbers:
    if num % 2 == 0:
        numbers.remove(num)
print(numbers)  # [1, 3, 5, 6], 6 was skipped

That 6 at the end should not be there. But because the list shrank while the loop was running, Python skipped over it entirely.

The clean fix is to iterate over a copy of the list while modifying the original, or better, use a list comprehension to build a new list instead of modifying in place.

numbers = [1, 2, 3, 4, 5, 6]
numbers = [num for num in numbers if num % 2 != 0]
print(numbers)  # [1, 3, 5]

I ran into the iteration bug on a data cleanup script I’d written for a client project. The script was removing invalid entries from a list of records. It ran without errors, but about 15% of the invalid entries stayed in. I spent two hours checking the condition logic before I realized the loop itself was the problem. One list comprehension fixed it in thirty seconds. The two hours, I did not get back.

The Extend vs Append Confusion

These two methods look similar but do completely different things. append() adds one item to the end of the list. extend() unpacks an iterable and adds each element individually.

a = [1, 2, 3]
a.append([4, 5])
print(a)  # [1, 2, 3, [4, 5]]
b = [1, 2, 3]
b.extend([4, 5])
print(b)  # [1, 2, 3, 4, 5]

With append, the entire list [4, 5] becomes a single nested element. With extend, the numbers 4 and 5 are added as separate items. Both are correct, depending on what you want. The problem is when you want one and use the other without realizing it.

This mistake usually shows up when merging data from multiple sources. You expect a flat list and get a list of lists instead, and everything downstream breaks.

Sort Doesn’t Return the List

This one is a classic. list.sort() sorts a list in place and returns None. A lot of developers, especially those coming from JavaScript or other languages, expect it to return the sorted list.

numbers = [3, 1, 4, 1, 5]
sorted_numbers = numbers.sort()
print(sorted_numbers)  # None

numbers is now sorted. But sorted_numbers holds nothing. If you need to assign the result, use the built-in sorted() function instead, which returns a new sorted list and leaves the original untouched.

numbers = [3, 1, 4, 1, 5]
sorted_numbers = sorted(numbers)
print(sorted_numbers)  # [1, 1, 3, 4, 5]
print(numbers)         # [3, 1, 4, 1, 5]

Knowing when to use sort() versus sorted() is a small thing, but it prevents a specific category of silent failures that are annoying to track down.

List Multiplication With Mutable Objects

This one is deceptive because it looks like it should work.

matrix = [[0] * 3] * 3
matrix[0][0] = 9
print(matrix)  # [[9, 0, 0], [9, 0, 0], [9, 0, 0]]

You changed one cell. All three rows changed. The * 3 operator didn't create three independent rows, it created three references to the same inner list. Changing one changes all of them.

The correct way to build a 2D list is with a list comprehension:

matrix = [[0] * 3 for _ in range(3)]
matrix[0][0] = 9
print(matrix)  # [[9, 0, 0], [0, 0, 0], [0, 0, 0]]

Each iteration of the comprehension creates a new list object, so the rows are independent.

What Ties All of This Together

Every bug in this article comes from the same root cause: Python lists are objects, and objects have identity, not just value. When you copy, loop, multiply, or sort a list, Python is working with references to objects in memory. That’s different from working with values directly.

Once that model clicks, these bugs stop being mysterious. You start seeing them coming instead of chasing them after the fact.

The good news is that Python gives you clean ways to handle all of these, list comprehensions, copy(), deepcopy(), sorted(). The tools are already there. You just need to know which one to reach for.

Thank you for being a part of the community

Before you go:

👉 Be sure to clap and follow the writer ️👏️️

👉 Follow us: **Linkedin| [Medium](https://medium.com/codetodeploy)**

👉 CodeToDeploy Tech Community is live on Discord — **Join now!**

Disclosure: This post includes affiliate and partnership links.


메타데이터
post_id
c557e1725a6b
slug
how-i-broke-my-code-without-touching-the-logic-c557e1725a6b
url
https://medium.com/codetodeploy/how-i-broke-my-code-without-touching-the-logic-c557e1725a6b
canonical_url
https://medium.com/codetodeploy/how-i-broke-my-code-without-touching-the-logic-c557e1725a6b
author_url
https://medium.com/@sanketparmar
status
ok
fetched_at
2026-06-24 04:09:36