TL;DR Use the Python module dis
to show students Python's bytecode alongside Java's bytecode. Avoid the "compiled v. interpreted" rabbit hole to start (because it may lead to more confusion than clarity) and instead show students what's actually happening underneath the hood.
Begin by defining "bytecode" in the context of Python. Here is the Python 3 documentation:
Python source code is compiled into bytecode, the internal
representation of a Python program in the CPython interpreter. The
bytecode is also cached in .pyc
files so that executing the same file
is faster the second time (recompilation from source to bytecode can
be avoided). This “intermediate language” is said to run on a virtual
machine that executes the machine code corresponding to each bytecode. [emphasies added]
Do note that bytecodes are not expected to work between different
Python virtual machines, nor to be stable between Python releases.
That might sound to students not too dissimilar from their experience with Java and its use of a virtual machine. Also, take a close look at the documentation for the dis
module.
Let's consider this very short Python program test.py
:
print("Hello, CSEducators.SE!")
If I run the command python -m dis test.py
, I see the following Python bytecode:
1 0 LOAD_NAME 0 (print)
3 LOAD_CONST 0 ('Hello, CSEducators.SE!')
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
Now, let's write Test.java
:
public class Test {
public static void main(String args[]) {
System.out.println("Hello, CSEducators.SE!");
}
}
I run javac Test.java
then javap -v Test.class
. Here's a small part of what I see:
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Hello, CSEducators.SE!
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 3: 0
line 4: 8
This is only a small part of it; the full output leaves a lot to explore. Nonetheless, at this point, students will see fewer differences than similarities (hopefully).
Additionally, consider this SO question: "Compiled vs. Interpreted Languages". It's not quite so black-and-white, and forcing it into a pure dichotomy may do more harm than good.
Let it be a bit messy. That's what learning is all about.