A Python Foot Gun

Suppose you’re building a graph and have written the following class definition in Python.

class Node:
	def __init__(self, children=[]):
		self.children = children

It’s a simple node class that has a list of children. You can pass a list of children when you create the object, or if you don’t supply one it defaults to an empty list.

There’s something very wrong with this code that’s somewhat obvious with hindsight, but I didn’t catch it until after some time in the debugger.

So you create a couple empty nodes and then start appending to each one’s children list. Straightforward enough. But what actually happens?

Turns out that because the list is defined in the constructor definition the nodes are actually sharing the same empty children list, so appending to one also appends to others. If you don’t immediately catch this it will slowly take a toll on your sanity as you watch your code seemingly develop a mind of its own.

Thankfully for me this was all in a piece of code less than 50 lines long so I was able to figure things out pretty quickly. I ended up just removing the children parameter from the constructor since I wasn’t really using it anyway and instead I set the children list to a new empty list defined in the constructor body.

This was a good reminder that getting more familiar with a language also means getting more familiar with all its foot guns.