Last fall, I had an interview that turned out to be challenging. While I did quite well on most of it, there was one question I simply could not answer. The question was this -- given the following code, what can you see as being a possible issue:
def append_list(x=[]):
x.append(1)
return x
I -- like many other people -- couldn't see anything wrong with this. I simply assumed the default parameter would be used in lieu of calling with an actual value. However, examine the following snippet. func1 is the aforementioned function. func2 is the proper definition:
#!/usr/bin/env python
def func1(x=[]):
x.append(1)
return 'x = %15s, id(x) = %s' % (x, id(x))
def func2(x=None):
if x is None:
x = []
x.append(1)
return 'x = %15s, id(x) = %s' % (x, id(x))
for f in (func1, func2):
print '%s %s' % (f.__name__, f())
print f.__name__, f()
print f.__name__, f()
print f.__name__, f([2])
print f.__name__, f()
print
The above snippet will produce something like the following. Have a close look:
$ ./gotcha.py func1 x = [1], id(x) = 3084437356 func1 x = [1, 1], id(x) = 3084437356 func1 x = [1, 1, 1], id(x) = 3084437356 func1 x = [2, 1], id(x) = 3084466828 func1 x = [1, 1, 1, 1], id(x) = 3084437356 func2 x = [1], id(x) = 3084466828 func2 x = [1], id(x) = 3084466828 func2 x = [1], id(x) = 3084466828 func2 x = [2, 1], id(x) = 3084466828 func2 x = [1], id(x) = 3084466828As you can see, func1's output is completely unexpected (well maybe not depending on who you are). The problem here has nothing to do with variable scope as I originally assumed. It's actually because I didn't understand Python variables and how they have some fundamental differences to other language implementations. This page has some very good explanations for several Python idioms. In fact, that link pretty much explains this behavior.
Leave a comment