Appendix 0 Part 2: Introduction to Programming with Python
March 2026 (8891 Words, 50 Minutes)
New to the terminal? Read Appendix 0 Part 1: Terminal and CLI Foundations first. This appendix assumes you can open a terminal and run commands.
This is the second part of the pre-course material. Part 1 taught you how to talk to your computer through a terminal. Now we answer a bigger question: why would you want to?
By the end of this appendix, you will:
- Understand why programming exists and what kinds of problems it solves
- Know why we use Python in this course
- Be able to write simple calculations, define functions, and create classes
- See how each programming concept emerges naturally from the limitations of the previous one
- Have a mental map that carries you through the rest of this course
This is pre-course reading. Work through it at your own pace. You do not need to memorize syntax – the goal is to build intuition for how programmers think.
1. Why Do People Write Programs?
Every piece of software you have ever used exists because someone had a problem and decided to solve it with code.
Think about the applications on your phone right now. Instagram exists because Kevin Systrom wanted a simple way to share photos with filters. Spotify exists because Daniel Ek wanted to make music accessible without piracy. Google exists because Larry Page and Sergey Brin wanted to find relevant information in a growing ocean of web pages. Netflix started mailing DVDs but then wrote software that could recommend movies better than any human clerk.
These are all problems that were solved with programs.
But software is not just consumer apps. Programming is everywhere:
- Science: CERN uses millions of lines of code to analyze particle collisions. Climate scientists run simulations to predict global temperatures decades into the future. Biologists write programs to compare DNA sequences across species.
- Engineering: NASA’s Mars rovers are controlled by software written on Earth. Automotive engineers simulate crash tests before bending a single piece of metal. Architects use computational tools to optimize building structures.
- Medicine: Machine learning models detect tumors in X-rays. Epidemiologists model how diseases spread. Pharmacologists simulate how drug molecules interact with proteins.
- Finance: Banks process millions of transactions per second. Algorithmic trading systems make decisions in microseconds. Risk models predict market behavior.
- Art and media: Pixar renders entire films with custom software. Musicians generate sound with code. Game developers build virtual worlds.
The common thread? Someone had a problem. Code was the tool to solve it.
1.1 From Big Ideas to Small Steps
Of course, you cannot sit down and build Netflix on your first day. The engineers at Netflix did not start there either – they started by learning the same fundamentals you are about to learn.
The trick to learning programming is finding problems that are small enough to solve today but meaningful enough to care about. Writing Hello World on the screen teaches you almost nothing, because it solves no real problem. But converting temperatures, analyzing data, or computing statistics – those are real tasks that use real thinking.
Throughout this appendix, we will work with a single running example: a weather station. Everyone understands weather. It involves numbers (temperatures, humidity, wind speed), text (city names, descriptions), and logical decisions (is it raining?). It is simple enough to start with, but rich enough to show you why each new programming concept matters.
Let us begin.
2. Why Python?
There are hundreds of programming languages. Why does this course use Python?
Three reasons:
1. No compilation step. In many languages (C, Java, Rust), you write code, then run a separate program called a compiler to translate it into something the computer can execute, and only then can you run it. Python skips the middle step. You write code and run it immediately. This makes experimenting fast and painless.
| Language | Step 1 | Step 2 | Step 3 |
|---|---|---|---|
| C | Write main.c |
Compile: gcc main.c -o main |
Run: ./main |
| Java | Write Main.java |
Compile: javac Main.java |
Run: java Main |
| Python | Write main.py |
Run: python main.py |
|
2. Designed for fast prototyping. Guido van Rossum created Python in 1991 with a philosophy: code should be easy to read, easy to write, and quick to turn an idea into a working program. Python was built for humans, not for machines.
3. The language of science and AI. Today, Python is the dominant language in data science, machine learning, scientific computing, and automation. Libraries like NumPy, Pandas, TensorFlow, and PyTorch are all Python-first. If you work with data or AI in any field, you will encounter Python.
Here is your first Python program. Open a terminal (you learned how in Part 1), create a file called hello.py, and run it:
# save this as hello.py
print("Hello from Python!")
$ python hello.py
Hello from Python!
That is it. No compiler. No build step. Write, run, see the result.
3. Elementary Data Types and Calculations
Any problem you want to solve with code requires some form of calculation. Programming languages give you basic building blocks to represent and manipulate data – numbers, text, and logical values. If you have done any math at all, you already understand these concepts.
3.1 Numbers and Strings: The Building Blocks
In math, you work with integers (1, 2, 3) and real numbers (3.14, 2.718). In Python, these are called int and float:
temperature_celsius = 23.5 # float (decimal number)
number_of_sensors = 4 # int (whole number)
city = "Aalen" # str (text, called a "string")
is_raining = False # bool (True or False)
A variable is simply a name attached to a value – think of it as a labeled box. You choose the name, Python remembers the value.
Notice print() – you have been using it since your very first hello.py and might not have thought twice about it. print() is a built-in function that Python gives you for free. You pass it a value, and it displays that value on the screen. You do not need to understand how it works inside – just that it takes something in and makes it visible. In Section 4, you will learn to write your own functions. When you get there, you will realize you have already been calling one since your first line of code.
You can also ask Python what type a value is by combining print() with another built-in function, type():
print(type(temperature_celsius)) # <class 'float'>
print(type(number_of_sensors)) # <class 'int'>
print(type(city)) # <class 'str'>
print(type(is_raining)) # <class 'bool'>
That is all you need to know about types for now. There are four basic ones:
| Type | What It Represents | Examples |
|---|---|---|
int |
Whole numbers | 0, 42, -7 |
float |
Decimal numbers | 3.14, -0.5, 23.5 |
str |
Text (strings of characters) | "Aalen", "hello", "42" |
bool |
Logical values | True, False |
3.2 Operators: Doing Math with Code
You know arithmetic. Python does too:
celsius = 23.5
# The classic conversion formula
fahrenheit = celsius * 9 / 5 + 32
print(fahrenheit) # 74.3
The arithmetic operators work exactly like you expect:
a = 10
b = 3
print(a + b) # 13 addition
print(a - b) # 7 subtraction
print(a * b) # 30 multiplication
print(a / b) # 3.33 division (always returns float)
print(a // b) # 3 integer division (rounds down)
print(a % b) # 1 modulo (remainder)
print(a ** b) # 1000 exponentiation (10 to the power of 3)
You can also compare values – the result is always a bool:
temperature = 23.5
print(temperature > 30) # False
print(temperature < 0) # False
print(temperature == 23.5) # True
print(temperature >= 20) # True
With just variables and operators, you can already do useful work. Let us convert a temperature:
# Weather station in Aalen reads 23.5 degrees Celsius
celsius_aalen = 23.5
fahrenheit_aalen = celsius_aalen * 9 / 5 + 32
print("Aalen:", fahrenheit_aalen, "F") # Aalen: 74.3 F
3.3 Collections: Lists
In the real world, you rarely deal with a single value. A weather station records temperatures every hour. You need a way to store multiple values together.
A list is an ordered sequence of values:
# Daily temperatures for one week in Aalen (Celsius)
daily_temps = [18.2, 21.0, 19.5, 23.5, 25.1, 22.8, 20.3]
print(daily_temps[0]) # 18.2 (first element, counting starts at 0)
print(daily_temps[3]) # 23.5 (fourth element)
print(len(daily_temps)) # 7 (number of elements)
You can loop through a list to process every element:
# Compute the average temperature
total = 0
for temp in daily_temps:
total = total + temp
average = total / len(daily_temps)
print("Average:", average) # Average: 21.485714285714288
Lists are powerful, but they are just containers. As your code grows, you will need more structure. Let us see why.
3.4 The Problem: Repetition
Suppose you monitor five cities. You need to convert each temperature to Fahrenheit:
# Five cities, five conversions
celsius_aalen = 23.5
fahrenheit_aalen = celsius_aalen * 9 / 5 + 32
celsius_berlin = 19.0
fahrenheit_berlin = celsius_berlin * 9 / 5 + 32
celsius_munich = 21.3
fahrenheit_munich = celsius_munich * 9 / 5 + 32
celsius_stuttgart = 20.7
fahrenheit_stuttgart = celsius_stuttgart * 9 / 5 + 32
celsius_hamburg = 16.8
fahrenheit_hamburg = celsius_hamburg * 9 / 5 + 32
This works. But look at the repetition. The same formula appears five times. Now imagine:
- What if you had 100 cities instead of 5?
- What if the conversion formula needed to change (perhaps you want to round to one decimal)?
- What if you made a typo in one line but not the others?
Copy-pasting code is a recipe for bugs. There must be a better way.
Try this now: Open the Guided Hands-On Notebook (Sections 1-2) and:
- Create a variable
celsiuswith today’s approximate temperature- Convert it to Fahrenheit using the formula:
fahrenheit = celsius * 9 / 5 + 32- Create a list of five temperatures and compute their average using a loop
4. Functions: Reuse Instead of Repetition
You already know functions from math class. If your teacher wrote:
\(f(x) = x \cdot \frac{9}{5} + 32\)
you would immediately understand: give me any value of \(x\), and I will return the result of that formula. You do not rewrite the formula every time – you just call \(f(23.5)\) and get 74.3.
Python functions work the same way.
4.1 From Math to Code
Here is the temperature conversion as a Python function:
def celsius_to_fahrenheit(celsius):
return celsius * 9 / 5 + 32
That is it. def means “define a function.” The name is celsius_to_fahrenheit. It takes one input (celsius) and returns one output. Now the five-city problem becomes:
def celsius_to_fahrenheit(celsius):
return celsius * 9 / 5 + 32
print("Aalen:", celsius_to_fahrenheit(23.5)) # 74.3
print("Berlin:", celsius_to_fahrenheit(19.0)) # 66.2
print("Munich:", celsius_to_fahrenheit(21.3)) # 70.34
print("Stuttgart:", celsius_to_fahrenheit(20.7)) # 69.26
print("Hamburg:", celsius_to_fahrenheit(16.8)) # 62.24
The formula exists once. If you need to change it, you change it in one place. If you have 100 cities, you just call the function 100 times.
Even better – combine it with a list:
cities = [
["Aalen", 23.5],
["Berlin", 19.0],
["Munich", 21.3],
["Stuttgart", 20.7],
["Hamburg", 16.8],
]
for city_data in cities:
print(city_data[0] + ":", celsius_to_fahrenheit(city_data[1]))
Five cities or five thousand – the code stays the same length.
4.2 Functions with Multiple Inputs and Outputs
Functions can take multiple parameters and return multiple values:
def analyze_temperatures(readings):
"""Analyze a list of temperature readings."""
min_val = min(readings)
max_val = max(readings)
avg_val = sum(readings) / len(readings)
return min_val, max_val, avg_val
daily_temps = [18.2, 21.0, 19.5, 23.5, 25.1, 22.8, 20.3]
lowest, highest, average = analyze_temperatures(daily_temps)
print("Lowest:", lowest) # 18.2
print("Highest:", highest) # 25.1
print("Average:", average) # 21.49
Functions are a huge step forward. They eliminate repetition and make your code readable. But as problems grow, functions alone are not enough.
4.3 The Problem: Too Many Loose Values
Your weather station records more than just temperature. It also tracks humidity, wind speed, the city name, and a timestamp. Now your function needs all of those:
def report_weather(city, temperature, humidity, wind_speed, timestamp):
fahrenheit = celsius_to_fahrenheit(temperature)
print(city, "at", timestamp)
print(" Temperature:", temperature, "C /", fahrenheit, "F")
print(" Humidity:", humidity, "%")
print(" Wind:", wind_speed, "km/h")
def feels_like(temperature, humidity, wind_speed):
# simplified wind chill calculation
return temperature - (wind_speed * 0.7)
# Calling these functions requires passing the same values over and over
report_weather("Aalen", 23.5, 65.0, 12.3, "2026-03-11 14:00")
wind_chill = feels_like(23.5, 65.0, 12.3)
Notice the problem? The values 23.5, 65.0, 12.3 belong together – they are all part of the same weather reading. But we pass them around as separate, loose values. What if you accidentally swap humidity and wind speed? Python will not complain. Your results will just be wrong.
When you find yourself passing the same group of values to multiple functions, those values are asking to be grouped together.
Try this now (Notebook Section 3):
- Write a function
celsius_to_fahrenheit(celsius)that converts Celsius to Fahrenheit- Write a function
feels_like(temp, humidity, wind)that returnstemp - (wind * 0.7)- Call both functions for three different cities
- Notice how many arguments you repeat each time
5. Classes: Grouping Related Data
Think of a class as a blank form – a template with labeled fields. A “Weather Reading Form” has fields for temperature, humidity, wind speed, and city name. Every time you fill out one of those forms, you create an instance – one specific reading with concrete values.
In Python, you define the form (the class) once, then create as many filled-out copies (instances) as you need.
5.1 Your First Class
class WeatherReading:
def __init__(self, city, temperature, humidity, wind_speed):
self.city = city
self.temperature = temperature
self.humidity = humidity
self.wind_speed = wind_speed
Let us unpack this:
class WeatherReading:– we are defining a new type of object calledWeatherReadingdef __init__(self, ...):– this special function runs when you create a new instance. Think of it as “filling out the form”selfrefers to the instance being created – the specific form you are filling out right nowself.temperature = temperaturestores the value inside the instance
Now create instances:
aalen = WeatherReading("Aalen", 23.5, 65.0, 12.3)
berlin = WeatherReading("Berlin", 19.0, 72.0, 8.5)
munich = WeatherReading("Munich", 21.3, 58.0, 15.1)
# Access individual fields with dot notation
print(aalen.city) # Aalen
print(aalen.temperature) # 23.5
print(berlin.humidity) # 72.0
The data that belongs together now lives together in one object.
5.2 Classes as Function Parameters
Remember the messy function with five parameters? With a class, it becomes clean:
# Before: five separate parameters
def report_weather(city, temperature, humidity, wind_speed, timestamp):
...
# After: one object that carries everything
def report_weather(reading):
fahrenheit = celsius_to_fahrenheit(reading.temperature)
print(reading.city)
print(" Temperature:", reading.temperature, "C /", fahrenheit, "F")
print(" Humidity:", reading.humidity, "%")
print(" Wind:", reading.wind_speed, "km/h")
report_weather(aalen) # clean, readable, no chance of swapping values
One parameter instead of five. No risk of swapping humidity and wind speed. And if you later add a pressure field to WeatherReading, you do not need to change the function signature at all.
5.3 The Problem: Functions That Live Separately from Their Data
We now have a WeatherReading class and standalone functions like celsius_to_fahrenheit and feels_like. But celsius_to_fahrenheit only makes sense in the context of a weather reading. And feels_like uses temperature, humidity, and wind_speed – which are all inside the WeatherReading object.
Why keep these functions separate from the data they operate on? Would it not make more sense to put them inside the class?
Try this now (Notebook Section 4):
- Define a
WeatherReadingclass withcity,temperature,humidity, andwind_speed- Create three instances for three different cities
- Store them in a list and loop through them:
stations = [aalen, berlin, munich] for station in stations: print(station.city, station.temperature)
6. Methods: Functions Inside Classes
A method is simply a function that lives inside a class and operates on that class’s data. Instead of passing data to a function from the outside, the method already has access to the data through self.
6.1 Adding Behavior to Data
Let us move our conversion and feels-like calculations inside the class:
class WeatherReading:
def __init__(self, city, temperature, humidity, wind_speed):
self.city = city
self.temperature = temperature
self.humidity = humidity
self.wind_speed = wind_speed
def to_fahrenheit(self):
return self.temperature * 9 / 5 + 32
def feels_like(self):
return self.temperature - (self.wind_speed * 0.7)
Compare the before and after:
# Before (standalone function): you pass the data in
feels_like(23.5, 65.0, 12.3)
# After (method): the object already has the data
aalen = WeatherReading("Aalen", 23.5, 65.0, 12.3)
aalen.feels_like()
The method version is cleaner: the object knows its own data and can perform calculations on it. You do not need to remember which values to pass – they are already inside the object.
Now you can process a list of stations elegantly:
stations = [
WeatherReading("Aalen", 23.5, 65.0, 12.3),
WeatherReading("Berlin", 19.0, 72.0, 8.5),
WeatherReading("Munich", 21.3, 58.0, 15.1),
]
for station in stations:
print(station.city)
print(" Fahrenheit:", station.to_fahrenheit())
print(" Feels like:", station.feels_like())
6.2 The __str__ Method: Making Objects Printable
If you try print(aalen) right now, you get something ugly:
<__main__.WeatherReading object at 0x7f8b2c3d4e50>
That is Python telling you “this is a WeatherReading object stored at memory address such-and-such.” Not very helpful. You can fix this by defining a special method called __str__:
class WeatherReading:
def __init__(self, city, temperature, humidity, wind_speed):
self.city = city
self.temperature = temperature
self.humidity = humidity
self.wind_speed = wind_speed
def to_fahrenheit(self):
return self.temperature * 9 / 5 + 32
def feels_like(self):
return self.temperature - (self.wind_speed * 0.7)
def __str__(self):
return (self.city + ": " + str(self.temperature) + " C, "
+ str(self.humidity) + "% humidity, "
+ str(self.wind_speed) + " km/h wind")
Now:
aalen = WeatherReading("Aalen", 23.5, 65.0, 12.3)
print(aalen)
# Aalen: 23.5 C, 65.0% humidity, 12.3 km/h wind
Methods whose names start and end with double underscores (like __init__ and __str__) are called dunder methods (short for “double underscore”). They let you customize how Python handles your objects. You will encounter more of them as you progress.
6.3 The Problem: A New Kind of Station
Your city installs advanced weather stations that also measure UV index and air pressure. You need a new class for these readings, but it should still do everything WeatherReading already does – convert to Fahrenheit, calculate feels-like temperature, print nicely – plus handle the new measurements.
Do you copy-paste the entire WeatherReading class and add two fields? That would work, but you would have two copies of the same code. If you fix a bug in one, you must remember to fix it in the other.
There must be a way to say: “I want a new class that already does everything this old class can do, plus more.”
Try this now (Notebook Section 5):
- Add a method
is_comfortable(self)to yourWeatherReadingthat returnsTrueif temperature is between 18 and 26 and humidity is below 70- Add a method
summary(self)that returns a formatted string like"Aalen: 23.5C, feels like 14.9C"- Create three instances and call both methods on each
7. Inheritance and Polymorphism: Extending What Already Works
“I want a new class that already does everything the old one could.”
That sentence is the entire motivation behind inheritance. You create a new class that inherits all the attributes and methods of an existing class, then add or change only what is different.
7.1 Building on Existing Classes
class AdvancedReading(WeatherReading):
def __init__(self, city, temperature, humidity, wind_speed, uv_index, pressure):
super().__init__(city, temperature, humidity, wind_speed)
self.uv_index = uv_index
self.pressure = pressure
Let us unpack this:
class AdvancedReading(WeatherReading):– the parentheses mean “this class inherits fromWeatherReading.”AdvancedReadingis the child,WeatherReadingis the parent.super().__init__(...)– calls the parent’s__init__to set up the fields thatWeatherReadingalready handles. No need to repeatself.city = cityand so on.- We only add what is new:
uv_indexandpressure.
Now the advanced reading can do everything the basic one can:
reading = AdvancedReading("Aalen", 23.5, 65.0, 12.3, 6.2, 1013.25)
# Inherited methods -- these just work!
print(reading.to_fahrenheit()) # 74.3
print(reading.feels_like()) # 14.89
print(reading.city) # Aalen
# New data
print(reading.uv_index) # 6.2
print(reading.pressure) # 1013.25
You wrote zero conversion or feels-like code for AdvancedReading. It inherited everything from WeatherReading for free.
7.2 Overriding Methods
What if the advanced station’s feels_like() calculation should also account for UV index? You can override the parent’s method by defining a new version in the child class:
class AdvancedReading(WeatherReading):
def __init__(self, city, temperature, humidity, wind_speed, uv_index, pressure):
super().__init__(city, temperature, humidity, wind_speed)
self.uv_index = uv_index
self.pressure = pressure
def feels_like(self):
# Start with the basic wind chill, then add UV impact
base = self.temperature - (self.wind_speed * 0.7)
uv_adjustment = self.uv_index * 0.5
return base + uv_adjustment
def __str__(self):
base = super().__str__()
return base + ", UV " + str(self.uv_index) + ", " + str(self.pressure) + " hPa"
Now AdvancedReading has its own feels_like() that considers UV, and its own __str__() that includes the extra fields. But to_fahrenheit() is still inherited unchanged from WeatherReading – no need to rewrite what already works.
7.3 One Interface, Many Types
Here is where things get powerful. You can mix basic and advanced readings in the same list and treat them uniformly:
stations = [
WeatherReading("Aalen", 23.5, 65.0, 12.3),
AdvancedReading("Berlin", 19.0, 72.0, 8.5, 3.1, 1015.0),
WeatherReading("Munich", 21.3, 58.0, 15.1),
AdvancedReading("Stuttgart", 20.7, 60.0, 10.2, 5.8, 1012.5),
]
for station in stations:
print(station.city, "- feels like:", station.feels_like())
Python calls the right version of feels_like() automatically. For WeatherReading objects, it uses the basic wind chill. For AdvancedReading objects, it uses the UV-aware version. Same method name, different behavior depending on the object’s type.
This is called polymorphism – from Greek: “many forms.” One interface, many implementations. And it is one of the most powerful ideas in programming.
And that is genuinely all you need to know about object-oriented programming for this course. Variables, functions, classes, methods, inheritance, polymorphism – you have the complete mental map.
Try this now (Notebook Section 6):
- Create an
AdvancedReadingclass that inherits fromWeatherReading- Add
uv_indexandpressurefields- Override
__str__to include the new fields- Create a mixed list of both types and loop through it calling
.feels_like()
8. Libraries and Imports: Standing on the Shoulders of Giants
You now know how to structure your own code. But here is a secret every experienced programmer knows: most of the code you need has already been written by someone else.
Python’s greatest strength is not just the language itself – it is the enormous ecosystem of libraries (also called packages or modules) that you can use for free. Why write your own statistics functions when Python includes one?
8.1 Built-in Libraries
Python comes with a “standard library” – a collection of modules that are always available, no installation needed:
import statistics
daily_temps = [18.2, 21.0, 19.5, 23.5, 25.1, 22.8, 20.3]
print(statistics.mean(daily_temps)) # 21.485714285714285
print(statistics.median(daily_temps)) # 21.0
print(statistics.stdev(daily_temps)) # 2.3380903889000912
Remember the loop we wrote earlier to compute the average? statistics.mean() does the same thing in one line – and it handles edge cases (like empty lists) that our loop did not.
Other useful built-in modules:
import math
print(math.sqrt(144)) # 12.0
print(math.pi) # 3.141592653589793
from datetime import datetime
now = datetime.now()
print(now) # 2026-03-11 14:30:00.123456
import random
print(random.randint(1, 6)) # a random dice roll
The import statement loads a module. from X import Y loads a specific piece from a module. That is all the syntax you need.
8.2 Third-Party Libraries
Beyond the standard library, there are hundreds of thousands of community-built packages. You install them with pip (or uv, which this course uses):
$ pip install numpy pandas matplotlib
You will encounter these throughout the course:
- NumPy – fast numerical computing with arrays
- Pandas – data analysis and manipulation
- Matplotlib – creating charts and plots
- Pytest – testing your code (you will use this a lot)
We will not dive deeper into these now. The important insight is this: programming is not about writing everything from scratch. It is about combining your code with existing tools to solve problems efficiently.
For a detailed guide on how Python modules and imports work, see Appendix 2: Python Modules.
8.3 Organizing Your Own Code into Modules
When your file gets long, you can split your code into multiple files. Put WeatherReading in its own file and import it elsewhere:
# In weather.py
class WeatherReading:
def __init__(self, city, temperature, humidity, wind_speed):
self.city = city
self.temperature = temperature
self.humidity = humidity
self.wind_speed = wind_speed
def to_fahrenheit(self):
return self.temperature * 9 / 5 + 32
# In main.py
from weather import WeatherReading
aalen = WeatherReading("Aalen", 23.5, 65.0, 12.3)
print(aalen.to_fahrenheit())
This is the same idea as using someone else’s library – except the library is your own code. The mindset is always the same: define once, reuse everywhere.
Try this now (Notebook Section 7):
- Use
import statisticsto compute the mean and standard deviation of your temperature list- Use
from datetime import datetimeto print the current date and time- Try
import thisin a Python terminal and read “The Zen of Python” – it is the philosophy behind Python’s design
9. The Big Picture: How It All Connects
Let us step back and see the path we traveled. Every concept was introduced because the previous one hit a wall:
| Concept | Problem It Solves | Python Syntax | Weather Example |
|---|---|---|---|
| Variables & Operators | Store and calculate values | x = 23.5 |
Convert one temperature |
| Functions | Eliminate repetition | def f(x): return ... |
Convert any temperature |
| Classes | Group related data | class X: ... |
Bundle city + temp + humidity |
| Methods | Attach behavior to data | def f(self): ... |
reading.to_fahrenheit() |
| Inheritance | Extend without rewriting | class Y(X): ... |
AdvancedReading adds UV |
| Polymorphism | One interface, many types | Same method, different behavior | Mixed station list |
| Imports | Reuse existing solutions | import X |
statistics.mean(temps) |
This progression is not arbitrary. It reflects how the field of programming itself evolved over decades. Early programs were just sequences of calculations. Functions were invented to manage complexity. Classes and objects emerged when programs grew large enough that grouping data with behavior became essential. Libraries arose because no one wants to solve the same problem twice.
You just walked the same path – in one afternoon.
10. What You Need for This Course
Take a breath. You have covered a lot of ground, and you do not need to memorize everything right now. This appendix gave you the conceptual map – the why behind each idea. The syntax will become second nature as you practice.
Here is what matters for the weeks ahead:
- Lecture 1 will walk you through setting up Python, Git, and VS Code. You will write and run real code from day one.
- Appendix 2 goes deeper into imports, modules, and packages when you are ready.
- Every lecture will build on the concepts from this appendix. When you encounter a class or a function in the course material, you will know why it exists – not just how to write it.
The most important thing to take away: programming is structured problem-solving. Every concept you learned today exists because it helps you solve problems more effectively. Keep that mindset, and the syntax will follow.
11. Quick Reference: Python Concepts at a Glance
A compact cheat sheet for the concepts covered in this appendix. Bookmark this page and come back whenever you need a reminder.
Variable assignment:
name = "Aalen"
temperature = 23.5
List:
temps = [18.2, 21.0, 19.5]
Function:
def celsius_to_fahrenheit(celsius):
return celsius * 9 / 5 + 32
Class with __init__:
class WeatherReading:
def __init__(self, city, temperature):
self.city = city
self.temperature = temperature
Method:
class WeatherReading:
def to_fahrenheit(self):
return self.temperature * 9 / 5 + 32
Inheritance:
class AdvancedReading(WeatherReading):
def __init__(self, city, temperature, uv_index):
super().__init__(city, temperature)
self.uv_index = uv_index
Import:
import statistics
from datetime import datetime
from weather import WeatherReading
Loop:
for station in stations:
print(station.to_fahrenheit())
Conditional:
if temperature > 30:
print("Hot!")
elif temperature > 20:
print("Nice.")
else:
print("Cool.")
12. Summary and Next Steps
Here is what you learned:
- Programming exists to solve problems – from small calculations to global-scale applications
- Python lets you go from idea to working code with no compilation step
- Variables and operators let you store data and compute results
- Functions eliminate repetition by encapsulating reusable logic
- Classes group related data into coherent objects
- Methods attach behavior directly to data
- Inheritance and polymorphism let you extend and specialize without rewriting
- Libraries let you build on the work of the global programming community
Each concept was motivated by a real limitation of the previous one. That is not a teaching trick – that is how programming actually works. You reach for new tools when old ones are not enough.
Where to go next:
- Appendix 0 Part 1: Terminal and CLI Foundations – if you have not read it yet
- Lecture 1: Modern Development Tools – hands-on setup of Python, Git, and VS Code
- Introduction to Modern Software Engineering – the big picture of the course
- Appendix 2: Python Modules – deep dive into imports and packages