Brandon Konkle
Brandon Konkle

Principal Engineer, type system nerd, Rust enthusiast, supporter of social justice, loving husband & father, avid comic & manga reader, 日本語を勉強してる。

I’m a Software Architect with more than 15 years of experience creating high performance server and front-end applications targeting web and mobile platforms, & today I lead a team at Formidable Labs.

Share


Tags


Bitten by Python's Pass-By-Reference

I just got bitten by an interesting bug related to Python's pass-by-reference feature. I had a class method (mymethod) with a keyword argument (mykwarg) that defaulted to {}. I thought that each time mymethod was called, if mykwarg wasn't passed then it would default to an empty dict.

In reality, when the class was read by Python it evaluated the {} and made the default value a reference to the dict in memory. So each time mymethod was called without passing mykwarg, it was defaulting to that memory reference which contained data from a previous use. Here's an example class:

:::python
class MyClass(object):
    def my_method(self, my_kwarg={}):
        return my_kwarg    

And here's an iPython shell session illustrating what I mean:

In [2]: first_class = MyClass()

In [3]: kwarg = first_class.my_method()

In [4]: kwarg
Out[4]: {}

In [5]: kwarg.update({'foo': 'bar'})

In [6]: kwarg
Out[6]: {'foo': 'bar'}

In [7]: kwarg = first_class.my_method()

In [8]: kwarg
Out[8]: {'foo': 'bar'}

In [9]: second_class = MyClass()

In [10]: other_kwarg = second_class.my_method()

In [11]: other_kwarg
Out[11]: {'foo': 'bar'}

The fact that the kwarg wasn't defaulting to a fresh dict each time led to a lot of confusion before I realized what was happening! There are a couple of ways to solve the issue, but the easiest is probably this:

:::python
class MyClass(object):
    def my_method(self, my_kwarg=None):
        my_kwarg = my_kwarg or {}
        return my_kwarg

I’m a Software Architect with more than 15 years of experience creating high performance server and front-end applications targeting web and mobile platforms, & today I lead a team at Formidable Labs.

View Comments