Why Python, Specifically
Every language claims to be simple, right up until you try to read one. Look at a working Python program you have never seen before, and notice how much of it you already understand.
You have not written a line of Python yet, and the next block of code is a real, working program. Read it before you read the explanation below it — you will understand more of it than you expect.
A language you can read before you can write it
scores = [78, 92, 65, 88]total = sum(scores)average = total / len(scores) if average >= 90: print("Grade: A")elif average >= 80: print("Grade: B")else: print("Grade: C")A list of four numbers, a total, an average, and a decision based on it. Nothing in that program is disguised. sum adds the list up. len counts it. The indentation is not decoration — it is how Python marks which lines belong to which decision, instead of wrapping them in curly braces the way many other languages do.
That readability is not an accident. Python was designed, from its first release in 1991, around the idea that code is read far more often than it is written, and that a language should optimise for the reader.
The design goes deep enough that it is written down inside the language itself. Type one line into any Python interpreter and it prints its own list of priorities.
$ >>> import this$ The Zen of Python, by Tim Peters $ Beautiful is better than ugly.$ Explicit is better than implicit.$ Simple is better than complex.Nobody expects you to memorise that. A language shipping its own design philosophy as an importable module is unusual, and it tells you what the people who built it were optimising for on every decision after this one.
What it is actually running underneath
When you run a Python file, nothing translates it directly into the ones and zeros your processor understands. The standard implementation, CPython, compiles your file into an intermediate form called bytecode, then an interpreter reads that bytecode one instruction at a time and carries it out.
That extra step is what makes Python interpreted rather than compiled in the sense C or Rust are. You never wait for a separate build step — you run the file and it goes — but every instruction is costing you a layer of translation that a compiled language paid for once, in advance.
You can actually see the evidence of this step on disk. Run a program that imports a second file, and Python quietly caches the compiled version so it does not have to redo the translation next time nothing in that file has changed.
$ python3 main.py$ ls __pycache__# helpers.cpython-312.pycThat .pyc file is the bytecode, sitting between your source and the interpreter. Delete __pycache__ entirely and nothing breaks — Python just regenerates it the next time it needs to.
The price of not being told in advance
Python never asks what type a variable is going to hold. You do not declare int or string before a name, the way you would in Java or C — a name can point at a number today and a list tomorrow, and nothing stops you. That is what dynamically typed means, and it is the other half of why Python reads so easily: there is less to write before you write the thing you actually meant.
The cost of that freedom is that Python cannot warn you about a type mistake before you run the program, because it never checked what any of your types were going to be in the first place. A statically typed language would refuse to compile the function below. Python compiles it happily, and only fails the moment this exact line actually executes — which might be seconds into a long-running program, or might be after it has already emailed a customer.
def total_price(items): return sum(item["price"] for item in items) print(total_price([{"price": 10}, {"price": "20"}]))$ python3 pricing.py$ Traceback (most recent call last): File "pricing.py", line 4, in <module> print(total_price([{"price": 10}, {"price": "20"}])) File "pricing.py", line 2, in total_price return sum(item["price"] for item in items)$ TypeError: unsupported operand type(s) for +: 'int' and 'str'One of the four prices was typed as text — "20" instead of 20 — probably because it came from a form field or a spreadsheet column that nobody checked. Nothing about the program looked wrong until Python tried to add an int and a string together and had no idea how.
Where speed gets traded for your time back
That translation layer has a real cost. A tight numeric loop written in raw Python can run tens of times slower than the same loop written in C. For a program that spends its life adding up sixty numbers, you would never notice. For a program processing billions of numbers, you would.
In practice, most Python code that needs to be fast is not slow, because it calls into libraries — for data, for machine learning, for anything numeric — that are themselves written in C underneath and only driven by Python. You get the reading and writing speed of Python and the execution speed of C, for the parts that actually run millions of times.
Good for
Scripts, data analysis, and backends — anywhere the real bottleneck is a database query or a network call, not the loop running while it waits.
Getting an idea running fast, because there is no compile step between changing a line and seeing what it does.
Awkward for
Shipping a native mobile app — nothing on iOS or Android runs Python directly, so it is never the tool for that job.
A CPU-bound inner loop with millions of iterations and no library to hand it off to — the exact case above.
Key takeaways
- Python is designed to be read, not just written — indentation marks structure instead of braces.
- CPython compiles your file to bytecode, then interprets it one instruction at a time.
- Python never checks a variable's type until the line using it actually runs, which is what dynamically typed means.
- That interpretation step is why raw Python loops run slower than raw C loops, and why fast Python code usually calls into C libraries instead of being fast itself.
- Do not optimise for speed before you have a program. Solve the problem first, then measure.
Quick check
Answer these to unlock the next chapter — 3 of 4 to pass. You can retake it anytime.
Answer every question to check.
Make a free account to read on
Every chapter is free — an account is how your progress, XP, and streak follow you from your laptop to your phone, and how you show up on the leaderboard. No payment, no trial.