How the Python Tutor visualizer can help students in your Python courses

Summary: This article is meant for instructors who teach Python, whether in university or K-12 classrooms. Python Tutor is a free web-based tool that draws step-by-step visualizations of code as it runs. Since 2010, over 25 million people in over 180 countries have used it to visualize over 500 million pieces of code. This article shows what it can illustrate at every level of Python teaching, from a student's first loop up through closures and generators. It will always remain free to use.

Read first: one-page quick-start guide for teachers


Python Tutor is a free tool that visualizes what your code does step-by-step as it runs. Since I created it in 2010, over 25 million people in over 180 countries have used it to visualize over 500 million pieces of code, and it's used for teaching in over 10,000 schools, including MIT, Harvard, Princeton, UC Berkeley, Tsinghua, and the IITs.

This article shows what it can illustrate across the full range of Python courses, from a student's very first loop up through closures and generators.

If you think this tool may be helpful for your students, please share this direct link in relevant course materials, chat groups, mailing lists, discussion forums, or social media:

This article starts with first-semester topics and works its way up. If you teach beginners, the first half may be all you need – feel free to stop whenever it goes past your course's level. And if you're more experienced, check out the "More Advanced Python" section near the end to see concepts (closures, generators) that other tools usually can't draw. All examples below are interactive: drag the slider under each one to step forward and back through execution, and click "Edit Code" under any example to open it in the full editor, where you and your students can modify and re-run it.

The Basics: Variables, Loops, and Conditionals

When students learn their first loops, teachers often have them trace code by hand, keeping a little table of each variable's value at each step. Python Tutor works like a self-updating trace table:

At the current step (Step 10), we're partway through the loop: day is 2 and total is 50. Students can step forward and backward to see every value this program ever computes. There's nothing to install or set up: students go to the website, type code, and press Visualize. Or they can click a link you send to them.

The visualizer also supports programs that read keyboard input from the user typing in a text box on the webpage. When execution reaches a call to input(), the visualizer prompts for a value, and then saves what the user types so that they can edit and re-run without retyping. Here's a loop that reads three test scores and averages them:

The "User inputs" panel below the code lists all three values that the user typed during this run. Here at Step 7 the first two are crossed out in gray because the code has already consumed them. Step backward and forward to watch each call to input() cross off each value right when it gets read.

Functions and the Call Stack

Each function call gets its own frame that holds its local variables:

At the current step, the frames for both checkout and add_tax are on screen at once. Stepping through shows values flowing into parameters and back out through return values (each function's return value is displayed just before its frame disappears).

Lists and Getting Surprised by Aliasing

In the example below why does a print as [1, 2, 3, 4] when the code appended to b?

Because b = a doesn't copy anything. Both names now refer to the same list, so the diagram shows two arrows pointing to one list. Note that list(a) creates an actual copy, which appears as a second list in the visualization.

This also happens when lists get passed to functions:

In the current step, replace_all has just reassigned its local name lst to a brand-new list, and there are now two separate lists on the heap: groceries still points at the original one (which add_item successfully mutated earlier), while the new ['coffee'] list is about to disappear when the function returns.

Dictionaries, Tuples, and Sets

Here's an example of using a dict as a running counter:

Tuples, sets, and some other collections from the standard library also render in similar ways.

Nested Data Structures

Python Tutor handles nested data structures by either using pointers or nesting, depending on what option you set.

Users can 'eyeball' what expressions like s['scores'][0] evaluate to by simply following the right arrows.

There's also a "show list-of-lists as 2D array" checkbox below the code editor, which is useful for seeing nested loops and matrix data structures:

Objects and Classes

For teaching object-oriented programming, the visualizer draws classes, instances, and method calls:

Here's an example of inheritance and method overriding:

Class objects (not just instances) appear on the heap, with Dog labeled as extending Animal. At the current step, the loop is calling speak() on Rex, so self points at the Dog instance and calls Dog's overriding method. Step back one iteration to see that same method call go to Animal's version.

Recursion

Python Tutor makes recursion easier to understand by showing all active frames on the stack, with each having their own private copies of local variables. For instance, here's the ultra-cliched recursive factorial example:

At the current step, four frames of factorial are visible, each holding its own n. Stepping forward shows each frame returning its result to its caller until the original call returns 24.

Exceptions

When an exception happens, rather than seeing a wall of error text, users can see exactly where an error occurred and the context around it. This can be useful when exceptions are caught by handlers or bubbled up through layers of function calls before being caught. Here's a simple example:

Note here how the red arrow jumps to the exception handler inside of except.

More Advanced Python

Everything below this point is for more advanced courses beyond CS1/CS2.

First, closures are something that almost no other tool draws correctly:

At this step make_counter already returned, yet its frame lives on (shown in light gray) because the nested increment function still refers to its count variable. The visualizer draws increment's frame with a link to that parent frame. It can cover features like nonlocal, lexical scoping, and functions carrying around their environment with them.

Related to above, it can also visualize generators:

Each time the for loop asks for another value, the countdown frame comes back onto the stack, resumes where it left off, and shows the value it's about to yield.

The visualizer can also illustrate some (simple) functional programming concepts:

At the current step, sorted is repeatedly calling the lambda, which runs in its own frame with its own n. In addition, default arguments, *args and **kwargs, and circular references display correctly (e.g., lst.append(lst) renders as a list pointing to itself). Lastly, the tool can visualize more advanced concepts like iterator protocols, dunder methods, descriptors, context managers, MRO (method resolution order), ABC (abstract base classes), and metaclasses.

Please Help Spread The Word!

Python Tutor can help your students see what their code actually does. It's free, it runs in the browser with nothing to install, and has been used by tens of millions since 2010.

Feel free to share this direct link in relevant course materials, chat groups, mailing lists, discussion forums, social media, or anywhere else:

And if you also teach Java, C/C++, or JavaScript, check out my companion articles on what the Java visualizer, C/C++ visualizer, and JavaScript visualizer can do.