There’s something I want you to learn. I can’t tell you what it is right now. You’ll have to trust me blindly and follow the instructions closely.
Part 1 ― Be a challengerWe’re going to look at some buggy python code. Don’t leave just yet if you have never written python before! You will find something to apply to you preferred everyday language, I promise. If I lied, you are allowed to insult me abundantly through your favorite channel (here’s my Twitter , you’re welcome). Here’s your code, commented so that you know what happens.
def foo(a, methods=[]): # methods defaults to [] if not specifiedfor i in range(3):
# Append an anonymous function, which returns `x + i`
# when given `x`
methods.append(lambda x: x + i)
sum_methods = 0
# For each function `method` of in `methods`, sum `method(a)`
for method in methods:
sum_methods += method(a)
return sum_methods
You expect your function to output the following:
foo(0) = (0 + 0) + (0 + 1) + (0 + 2) = 3 foo(1) = (1 + 0) + (1 + 1) + (1 + 2) = 6 foo(2) = (2 + 0) + (2 + 1) + (2 + 2) = 9 foo(2, [lambda x: x]) = ((2)) + ((2 + 0) + (2 + 1) + (2 + 2)) = 11Simple, right? Let’s try it in our terminal.
>>> foo(0)6
>>> foo(1)
18
>>> foo(2)
36
>>> foo(2, [lambda x: x])
14
Well, there seems to be a minor error. But wait, could we have missed something? Let’s check again.
>>> foo(0)24
>>> foo(1)
45
>>> foo(2)
72
WHAT.
THE.

He’s not screaming what youthink he is
But, you’re not going to get beaten down by this, right? You will pull your shirtsleeves up your arms (provided you wear a shirt, which would be unusual but we’re not judging), and you will find out what is wrong using well-placed print statements or other debugging practices you know.
Set a stopwatch, try to debug the code by clicking here , and please let me know how much time it took you to understand and fix what’s wrong in the comments, and what practices you used . K eep both for loops and don’t change the foo function calls because it would be too easy. Got it? Go!
Part 2 ― Behold theLightBefore jumping to the answer, let’s talk about debuggers. Every language I know has a way to be debugged. Debuggers lets you explore each line of the code in a convenient way.
Every debugger has at least the following commands, that you can use directly in python code:
Set a break point, where the execution will halt: pdb.set_trace() . I usually set my breakpoints with import pdb; pdb.set_trace() since Python is not bothered with importing the same library several times and in an inline fashion. C ontinue until next break point: c N ext line: n L ist the surrounding code: l H elp: hDebuggers are Life
― Experts
So how much quicker could you have been by using a debugger instead of trial-and-error and print statements?
I’ve tried this hypothesis on two separate groups of people: one where they used print statements, and one where they used the debugger. The second group took 9 minutes on average, and the first one 14 minutes! Those are not completely statistically significant, but that’s still a 35% speedup on an 8-line-long program .
Now imagine you encountered these bugs hidden in a much bigger program? I know a lot of developers that spend hours debugging a bug with print statements and waste a lot of time. The challenge is to find out exactly where you are in the code, but you get used to it very quickly, either by setting a lot of breakpoints, or by using the l command. Debuggers walk you through the code and they make understanding some new code much easier.

Mia found out about debuggers at an early age and is still amazed! Be likeMia.
Do you want your solution then? I’ve made a video of me using a python debugger (don’t mind the occasional typos please). It’s a bit long but I kept it real-time so you can see the debugging process more clearly. Here’s the video:
Additional info: methods was broken because lists in python are mutable objects. It means that when methods is set to the default value (the empty list) and is then changed, the default value is also updated (and becomes the empty list with one more element). This is a common pitfall that you can fix using a None default value. Here is the full corrected code:
def methods_generator(i): # Scopes the i to not overwrite itreturn lambda x: x + i
def foo(a, methods=None):
if methods is None: #Prevents the default value to be changed
methods = []
for i in range(3):
methods.append(generate_lambda(i))
sum_methods = 0
for method in methods:
sum_methods += method(a)
return sum_methods Part 3 ― Debugging resources
I promised I would write about other languages, and I will keep this promise right now! Here are useful resources I came across, please don’t hesitate to submit more! I also included code linting practices which will highlight your errors in your code.
php Configuring PHPStorm with XDebug through a Vagrant machine An Atom package for PHP debugging PHP linter in Atom A stackoverflow topic on linting in PHP javascript To debug your front-end code, you can set a breakpoint by typing debugger anywhere in your code. The execution will halt only if you have the developper tools opened in your browser! Make sure you don’t commit it:).