Introduction to Python
Python is a high-level, dynamically and strongly typed, multi-paradigm language built around readability — this topic maps out where it came from, how it compares to other languages, and what running Python actually means.
Python is a general-purpose, high-level programming language first released by Guido van Rossum in 1991. It emphasizes code readability, a clean and consistent syntax, and a "batteries included" standard library, which together have made it one of the most widely used languages for scripting, web development, data science, automation, and teaching programming itself. This topic gives you the map before you start filling in the territory: what Python is, where it came from, how its type system and execution model actually work, and how it stacks up against C/C++, Java, and JavaScript.
What Python Is
Python is a general-purpose, high-level programming language. "High-level" means it manages low-level details for you — memory allocation, pointer arithmetic, and manual type declarations are not things you deal with directly, unlike in C. Python is also an interpreted language in its usual usage: you run source code through the Python interpreter rather than compiling it ahead of time to a native executable (the section below on the execution model refines this claim carefully).
Python is used as a scripting language, an application language, and increasingly as the default language for data science, machine learning, automation, and backend web development. Its core design goal, stated explicitly by its creator, is that code should be easy to read and easy to reason about — even by someone who didn't write it.
A complete, runnable Python program. No boilerplate, no explicit main function is required, no semicolons.
print("Hello, World!")History and Origin
Python was created by Guido van Rossum, a Dutch programmer, and first released in 1991. Van Rossum began the project in December 1989 as a hobby to keep himself occupied over the Christmas holidays, as a successor to a teaching language called ABC that he had worked on at Centrum Wiskunde & Informatica (CWI) in the Netherlands. The name "Python" is a reference to the British comedy group Monty Python's Flying Circus, not the snake — a nod to the language's intended tone of not being deathly serious.
Van Rossum served as Python's "Benevolent Dictator For Life" (BDFL), the final authority on language design decisions, until he stepped back from that role in 2018. Python's evolution since then is governed by the Python Steering Council together with the PEP (Python Enhancement Proposal) process, a formal mechanism for proposing, discussing, and accepting changes to the language.
Design Philosophy
Python's design philosophy is captured, half-seriously, in "The Zen of Python" (PEP 20), a short list of aphorisms you can read at any time by running import this. A few of its most influential lines: "Beautiful is better than ugly," "Explicit is better than implicit," "Simple is better than complex," "Readability counts," and "There should be one — and preferably only one — obvious way to do it."
Prints the full Zen of Python to the console — a real, working easter egg built into the language itself.
In practice this philosophy shows up as: significant indentation instead of braces (forcing visually consistent code), a large standard library ("batteries included") so common tasks don't require third-party packages, and a strong cultural preference (formalized in PEP 8, the official style guide) for one conventional way to format and name things.
import this"Interpreted" and "Compiled" — Explained Carefully
It is common to hear "Python is an interpreted language" stated as a blunt fact, but this glosses over what actually happens. Compilation and interpretation are not mutually exclusive — they describe different stages of how source code becomes running behavior, and most real Python implementations do both.
In CPython (the reference implementation, and the one almost everyone means by "Python"), your .py source is first compiled to an intermediate form called bytecode — a compact, platform-independent instruction set — and that bytecode is then interpreted by a virtual machine written in C. So Python code is compiled (to bytecode) and then interpreted (by the bytecode VM); there is no single native-machine-code compilation step the way there is for C, and no separate "compile" command you run ahead of time — the compilation to bytecode happens automatically and transparently as part of running your program.
The precise mechanics of this — the .pyc cache, the compile/import pipeline, and the REPL — are covered in depth in the Python Execution Model topic. The point here is just: don't say "Python has no compilation step." It does; it's just automatic, to bytecode, and not to native machine code by default.
Dynamically Typed and Strongly Typed
Python is dynamically typed: you never declare the type of a variable, and a single name can be rebound to point at objects of different types over its lifetime. It is important to phrase this correctly — Python variables don't lack types; rather, names are bindings to objects, and every object has a definite type. The name itself carries no type information; only the object it currently refers to does.
type(x) reports the type of whatever object x currently refers to, not a fixed "declared type" of x itself.
Python is also strongly typed: it does not silently coerce values between unrelated types. Contrast this with weakly typed languages like JavaScript, where "5" + 3 might silently produce "53". In Python, mixing incompatible types raises an exception rather than guessing at your intent.
x = 5 # x is bound to an int object
x = "hello" # x is now bound to a str object — the object 5 still had type int
print(type(x))"10" + 5 # TypeError: can only concatenate str (not "int") to strMulti-Paradigm
Python does not force a single programming style. It supports procedural programming (plain functions and statements), object-oriented programming (classes, inheritance, polymorphism), and functional-style programming (first-class functions, map/filter, comprehensions, closures) — and it's common, even idiomatic, to mix all three within one program. This flexibility is part of why Python fits such a wide range of domains, from quick scripts to large object-oriented frameworks.
Python Implementations
"Python" is a language specification; there are multiple implementations of it. Knowing they exist — at a high level — matters because language guarantees differ from implementation details, a distinction this entire course is careful about.
This course, like most Python material, targets CPython unless stated otherwise. Wherever a behavior described is specific to CPython's implementation (rather than guaranteed by the Python language itself), it will be explicitly labeled "CPython implementation detail."
CPython - the reference implementation, written in C. What "python" means by default.
Has the GIL (Global Interpreter Lock) in its traditional builds.
PyPy - an alternative implementation with a Just-In-Time (JIT) compiler,
often dramatically faster for long-running, CPU-heavy pure-Python code.
Jython - runs on the Java Virtual Machine; lets Python code interoperate with Java classes.
IronPython - runs on .NET's CLR; lets Python code interoperate with .NET libraries.Major Python Versions
Python 2 and Python 3 coexisted for many years and are not source-compatible — Python 3 (first released in 2008) made deliberate breaking changes to fix long-standing design issues (for example, print became a function instead of a statement, and integer division and string/text handling changed). Python 2 reached its official end of life on January 1, 2020, and is no longer maintained. Modern Python development targets Python 3 exclusively.
Within Python 3, minor versions (3.8, 3.9, 3.10, 3.11, 3.12, 3.13, ...) are released roughly annually and each adds meaningful new syntax or standard-library features — for example, f-strings (3.6), the walrus operator := (3.8), builtin generic types like list[int] (3.9), structural pattern matching with match/case (3.10), exception groups and except* (3.11), and a new, simpler generic type-parameter syntax (3.12). This course targets modern Python (3.12+) and will call out version-gated features by version as they come up.
Applications of Python
Python's breadth of use is unusually wide for a single language:
Everything listed as "third-party" above is a separately installed package, not part of the Python standard library that ships with the interpreter.
Web development - Django, Flask, FastAPI (all third-party frameworks)
Data science / ML - NumPy, pandas, scikit-learn, PyTorch, TensorFlow (third-party)
Automation / scripting- system administration, build tools, glue code
Scientific computing - simulations, numerical analysis
Education - widely used as a first teaching language
Automation & testing - pytest and general test-automation tooling (third-party)
Embedded/desktop tools- CLI utilities, small GUI appsAdvantages and Limitations
Advantages: readable, low-ceremony syntax; a huge standard library and third-party ecosystem; fast to prototype in; strong community and documentation; genuinely multi-paradigm; runs everywhere CPython (or another implementation) is available.
Limitations, stated carefully: Python is not the fastest language for raw computation, but "Python is slow" is an oversimplification — actual performance depends heavily on the workload, the algorithm chosen, whether you're calling into native-code libraries (like NumPy, which does its heavy lifting in C), and whether the bottleneck is CPU-bound or I/O-bound. For CPU-bound parallel work, CPython's traditional GIL (see the CPython Implementations section) limits true multi-core parallelism within a single process, which is why CPU-bound workloads often reach for the multiprocessing module or native extensions, while I/O-bound concurrency is well served by asyncio or threading.
Python versus C/C++
The core trade-off: C/C++ give you fine-grained control over memory and hardware at the cost of verbosity and manual bookkeeping; Python trades some raw performance and low-level control for dramatically faster development and fewer categories of bugs (no manual memory management, no raw pointers by default).
Python C / C++
Typing dynamic, strong static, weak-ish (C) / static, strong (modern C++)
Memory managed automatically manual (C) or RAII/manual (C++)
Compilation compiled to bytecode, then compiled ahead-of-time to native machine code
interpreted by a VM
Speed generally slower for raw generally faster for raw compute; no
compute; fast to write interpreter overhead
Typical use scripting, web, data science, systems programming, OS kernels, embedded,
automation, prototyping performance-critical applicationsPython versus Java
Both Python and Java run on a virtual machine and both manage memory automatically. The biggest difference is typing discipline: Java is statically typed (types are checked and fixed at compile time, and you must declare them), while Python is dynamically typed (types are checked at runtime, and variables carry no declared type). Java requires more verbose ceremony — explicit class declarations, access modifiers, checked exceptions — where Python favors terser, more implicit syntax. Java's JIT-compiled JVM is typically faster for long-running CPU-heavy programs than CPython's bytecode interpreter, though PyPy narrows that gap for pure-Python workloads.
Python versus JavaScript
Both are dynamically typed, high-level, interpreted-in-practice languages with large ecosystems — but Python is strongly typed while JavaScript is comparatively weakly typed and coerces aggressively between types (e.g., "5" + 3 produces "53" in JavaScript, but "10" + 5 raises a TypeError in Python). JavaScript's concurrency model is fundamentally single-threaded and event-loop-based by design across all major environments; Python offers multiple concurrency models (threading, multiprocessing, asyncio) suited to different problems, though CPython's GIL shapes how threading behaves for CPU-bound work.
Your First Python Program
By convention, the first program in any language prints a greeting. In Python, this requires exactly one line — no imports, no class wrapper, no explicit entry-point function are needed for a simple script.
Running the script from a terminal. The exact command (python vs python3) depends on your system's installation.
print("Hello, World!")$ python hello.py
Hello, World!Key Takeaways
Python is a high-level, general-purpose, dynamically and strongly typed, multi-paradigm language created by Guido van Rossum, first released in 1991.
"Interpreted" doesn't mean "no compilation" — CPython compiles source to bytecode, then interprets that bytecode; there's no separate ahead-of-time native-code compilation step by default.
Dynamic typing means names are unlabeled bindings to typed objects, not that objects themselves lack types.
Strong typing means Python refuses to silently coerce between unrelated types — mismatches raise TypeError rather than guessing.
CPython is the reference implementation; PyPy, Jython, and IronPython are alternative implementations with different trade-offs.
Never say "Python is slow" or "Python has a GIL" as blanket facts — performance and the GIL are workload- and implementation-specific.
CPython does compile — just to bytecode, not to native machine code, and it happens transparently rather than as a separate developer-run step.
type(x) always returns something meaningful — the object x currently points to has a type, even though the name x itself was never declared with one.
print "Hello, World!" # Python 2 syntax print("Hello, World!") # Python 3: print is a function
This course targets Python 3, where print is a builtin function and requires parentheses; the bare print statement is obsolete Python 2 syntax.
Is it accurate to say Python has no type system because variables aren't declared with types? Explain.
No. Python is dynamically typed, meaning names carry no type declaration — but every object a name refers to has a definite, well-defined type. type(x) always reveals that object's type. The type system exists; it's just checked at runtime against objects, not enforced at compile time against variable declarations.
Why is calling Python 'strongly typed' compatible with it also being 'dynamically typed'? Aren't those contradictory?
They describe independent axes. Dynamic vs static is about when types are checked (runtime vs compile time). Strong vs weak is about whether the language silently coerces between unrelated types. Python checks types at runtime (dynamic) but refuses silent coercion between unrelated types like str and int (strong) — "10" + 5 raises TypeError rather than guessing.
What is CPython, and how does it relate to 'Python' as most people use the term?
CPython is the reference implementation of the Python language, written in C. When people say "Python" or run the python command, they almost always mean CPython. Other implementations (PyPy, Jython, IronPython) implement the same language but with different internals and trade-offs.
Why is it misleading to say 'Python is an interpreted language' without qualification?
Because CPython does compile source code — to bytecode, an intermediate instruction format — before a virtual machine interprets that bytecode. The confusion is that there's no separate ahead-of-time step producing native machine code the way C's compiler does; the bytecode compilation happens automatically as part of running the program.
Name two Python implementations other than CPython and one thing each is used for.
PyPy uses a JIT compiler and is often much faster for long-running, CPU-heavy pure-Python programs. Jython runs on the JVM and lets Python code interoperate with Java libraries. (IronPython, similarly, targets .NET.)
A colleague says 'Python is just slow, avoid it for anything performance-sensitive.' How would you respond?
Performance depends on the workload. Pure interpreted-loop-heavy Python code can indeed be slower than compiled languages, but Python programs that lean on native-code libraries (NumPy, pandas), use the right algorithm, or offload CPU-bound work to multiprocessing or C extensions can be highly performant. I/O-bound workloads are well served by asyncio regardless. Blanket claims about a language's speed ignore how the work is actually structured.
What does the PEP process govern, and who currently makes final decisions about the Python language?
PEPs (Python Enhancement Proposals) are the formal mechanism for proposing, discussing, and documenting changes to the Python language and its standard library. Since Guido van Rossum stepped down as BDFL in 2018, the Python Steering Council makes final governance decisions, informed by the PEP process and community discussion.
Write the classic first program: print the exact text 'Hello, World!' to the console.
print("Hello, World!") Running python hello.py with this content prints exactly: Hello, World!
What does this print, and why is this legal in Python?
It prints <class 'list'>. This is legal because Python names are dynamically-typed bindings — x is simply rebound to a new object each time, regardless of that object's type. type(x) reports the type of whatever object x currently refers to.
What happens when this line runs, and why?
It raises TypeError: can only concatenate str (not "int") to str. Python is strongly typed and will not silently coerce the int 5 into a string to satisfy the + operator — you must convert explicitly, e.g. "Score: " + str(5).
Write a one-line program that imports and displays the Zen of Python.
Running this script prints the 19 aphorisms of PEP 20 ("The Zen of Python"), starting with "Beautiful is better than ugly." It's a real, functioning easter egg in the standard library.
x = 10
x = "ten"
x = [10]
print(type(x))result = "Score: " + 5