Lesson 4 · Python for Data Analysts
Python for Beginners: From Variables to Real Mini Projects
By the end, you'll have built three real mini projects: a deadline countdown tool, a spreadsheet automation script, and a program that talks to a live web…
- CoursePython for Data Analysts
- Lesson4 of 12
- Video1 h 1 min
- FormatJupyter notebook · 44 code cells
- Data1 dataset
What you'll learn
Datasets used in this lesson
Save these next to the notebook. In Google Colab, upload them with the 📁 icon on the left first.
- inventory.xlsx5.7 KB
📓 Full notebook
Download .ipynbPython for Beginners: From Variables to Real Mini Projects#
- By the end, you'll have built three real mini projects: a deadline countdown tool, a spreadsheet automation script, and a program that talks to a live web API.
- No prior experience needed. Let's jump straight in.
Before You Start#
- Install Python 3 from python.org (on Windows, check 'Add python.exe to PATH'), then install VS Code from code.visualstudio.com with its Python and Jupyter extensions.
- Open the Command Palette (Control/Command plus Shift plus P), run 'Create: New Jupyter Notebook', and select your Python interpreter as the kernel.
Your First Cell: print()#
print(1)
print(200)
print('some sentence')
Data Types: Strings and Numbers#
- Text values are called strings, and can be written with either single or double quotes; there is no difference between the two.
- Whole numbers, like 2, 20, 0, or -5, are integers.
- Numbers with a decimal point, like 4.99, are floats, used whenever you need precision, like a price or a weight.
a_string = 'Hello there'
an_integer = 20
a_float = 4.99
print(type(a_string))
print(type(an_integer))
print(type(a_float))
Combining Text and Numbers#
- Let's write a tiny calculation and then describe the result in a full sentence.
- We'll calculate how many minutes there are in a given number of days.
days = 20
hours_per_day = 24
minutes_per_hour = 60
total_minutes = days * hours_per_day * minutes_per_hour
print(total_minutes)
message = str(days) + ' days are ' + str(total_minutes) + ' minutes'
print(message)
message = f'{days} days are {total_minutes} minutes'
print(message)
Variables Avoid Repetition#
- Notice that hours_per_day and minutes_per_hour never change, no matter how many days we convert.
- Storing repeating values in well-named variables, instead of retyping them everywhere, is one of the most common things you'll do in any program.
days = 35
total_minutes = days * hours_per_day * minutes_per_hour
print(f'{days} days are {total_minutes} minutes')
days = 110
total_minutes = days * hours_per_day * minutes_per_hour
print(f'{days} days are {total_minutes} minutes')
Functions: Avoiding Repeated Logic#
- Variables help us avoid repeating single values, but what if we want to avoid repeating an entire calculation?
- A function is a named, reusable block of code. We define one with def, a name, parentheses, and a colon.
def days_to_minutes():
total = days * hours_per_day * minutes_per_hour
print(f'{days} days are {total} minutes')
days_to_minutes()
Function Parameters#
def days_to_minutes(num_days):
total = num_days * hours_per_day * minutes_per_hour
print(f'{num_days} days are {total} minutes')
days_to_minutes(20)
days_to_minutes(35)
Multiple Parameters#
def days_to_minutes(num_days, note):
total = num_days * hours_per_day * minutes_per_hour
print(f'{num_days} days are {total} minutes ({note})')
days_to_minutes(20, 'a short sprint')
days_to_minutes(110, 'nearly four months')
Returning Values From a Function#
- So far our function prints its own result. Often you instead want a function to hand a value back to you, so you can use it elsewhere.
- We do that with the return keyword.
def days_to_minutes(num_days):
total = num_days * hours_per_day * minutes_per_hour
return f'{num_days} days are {total} minutes'
result = days_to_minutes(20)
print(result)
Variable Scope: Local vs. Global#
- Variables created outside any function, like hours_per_day and minutes_per_hour, are global: every function in your code can read them.
- Variables created inside a function, like num_days or total above, are local: they only exist while that function is running, and only that function can see them.
def show_scope():
print(minutes_per_hour)
print(total)
show_scope()
Getting Input From the User#
- Every program so far has used hard-coded values. Real programs usually need to ask the person using them for information.
- The built-in input function pauses your program, shows an optional prompt message, and waits for the user to type something and press Enter.
user_input = input('Enter a number of days: ')
print(user_input)
print(type(user_input))
Type Conversion (Casting)#
- Because input always returns a string, using it directly in a math calculation causes problems, since Python can't multiply text.
- We fix this with casting: converting a value from one data type to another, using functions like int(), float(), and str().
user_input = input('Enter a number of days: ')
total = user_input * hours_per_day * minutes_per_hour
print(total)
user_input = input('Enter a number of days: ')
num_days = int(user_input)
total = num_days * hours_per_day * minutes_per_hour
print(f'{num_days} days are {total} minutes')
Conditionals: if, elif, else#
- A negative number of days doesn't make sense for our converter, so let's validate the user's input before doing any math.
- if, elif, and else let a program branch: run one block of code when a condition is true, and a different block otherwise.
num_days = -10
if num_days > 0:
total = num_days * hours_per_day * minutes_per_hour
print(f'{num_days} days are {total} minutes')
elif num_days == 0:
print('You entered zero, please enter a valid positive number.')
else:
print('You entered a negative value, no conversion for you.')
Comparison Operators and Booleans#
- Greater than, less than, and equals are called comparison operators, because they compare two values.
- Every comparison produces a value of its own data type: a boolean, which is either True or False, always capitalized in Python.
is_positive = num_days > 0
print(is_positive)
print(type(is_positive))
Handling Errors Gracefully With try/except#
- if statements are great for validating specific rules, like 'is this positive'. But what if the user types text instead of a number at all?
- try/except lets us attempt some code, and catch a specific type of error if it happens, instead of letting the whole program crash.
try:
user_input = input('Enter a number of days: ')
num_days = int(user_input)
print(f'You entered {num_days} days.')
except ValueError as e:
print('That is not a valid number:', e)
while Loops: Repeating Until a Condition Changes#
- Right now our program asks for input exactly once, then ends. What if we want to keep converting values until the user decides to stop?
- A while loop repeats its body for as long as its condition stays True.
user_input = ''
while user_input != 'exit':
user_input = input("Enter a number of days, or 'exit' to stop: ")
if user_input == 'exit':
pass
elif user_input.isdigit():
print(f'{user_input} days are {int(user_input) * hours_per_day * minutes_per_hour} minutes')
else:
print('Please enter a whole number, or exit to stop.')
print('Goodbye!')
Lists: An Ordered Collection of Values#
- What if we wanted to convert several different day counts at once, without typing them in one at a time?
- A list is a data type that holds multiple values, in order, written with square brackets.
days_list = [10, 45, 30]
print(days_list)
print(days_list[0])
print(days_list[2])
days_list.append(90)
print(days_list)
for Loops: Doing Something for Every Element#
- Most of the time, when you have a list, you want to do the same thing to every element in it.
- A for loop runs its body once for each element in a list, automatically, with no manual indexing required.
for num_days in days_list:
total = num_days * hours_per_day * minutes_per_hour
print(f'{num_days} days are {total} minutes')
Sets: Only Unique Values#
- Suppose someone accidentally enters the same day count twice; a list happily keeps both copies.
- A set is like a list, but it automatically removes duplicates, and is written with curly braces.
days_with_duplicates = [10, 45, 30, 10]
unique_days = set(days_with_duplicates)
print(days_with_duplicates)
print(unique_days)
print(type(unique_days))
Built-in Functions vs. Methods#
- print, input, int, and set are all built-in functions: Python provides them ready to use, called by name with parentheses.
- Some functions instead belong to a specific data type, and are called directly on a value with a dot, like 'hello'.upper(); these are called methods.
greeting = 'hello there'
print(greeting.upper())
print(greeting.title())
print('42'.isdigit())
Dictionaries: Key-Value Pairs#
- Lists and sets are great for a bunch of similar values, but sometimes each value needs its own label.
- A dictionary stores key-value pairs, written with curly braces, where each key maps to a specific value.
conversion = {'days': 20, 'unit': 'hours'}
print(conversion)
print(conversion['days'])
print(conversion['unit'])
def convert(num_days, unit):
if unit == 'hours':
return f'{num_days} days are {num_days * 24} hours'
elif unit == 'minutes':
return f'{num_days} days are {num_days * 24 * 60} minutes'
else:
return f'Unsupported unit: {unit}'
print(convert(conversion['days'], conversion['unit']))
print(convert(5, 'minutes'))
print(convert(5, 'weeks'))
Comments#
- A comment starts with a #, and is completely ignored when your code runs.
- Use comments to leave notes for yourself or teammates, explaining why code does something, not just what it does.
# Convert days into the requested unit, defaulting gracefully for unknown units
print(convert(3, 'hours'))
Mini Project 1: Countdown to a Goal#
- Let's build something genuinely useful: a program that takes a goal and a deadline date, and tells you how many days remain.
- This needs a new built-in module, datetime, for working with dates.
from datetime import datetime
user_input = input('Enter your goal and deadline as goal:DD.MM.YYYY: ')
goal, deadline_text = user_input.split(':')
print(goal)
print(deadline_text)
deadline_date = datetime.strptime(deadline_text, '%d.%m.%Y')
print(deadline_date)
print(type(deadline_date))
today = datetime.today()
time_remaining = deadline_date - today
print(today)
print(time_remaining.days)
message = f'Time remaining for your goal "{goal}" is {time_remaining.days} days.'
print(message)
Modules: Organizing Code Across Files#
- Every Python file is a module: a container of functions, variables, and classes that other files can reuse.
- We already used one: 'from datetime import datetime' imports the datetime class out of Python's built-in datetime module.
- In a larger project you'd split your own code across multiple .py files too, for example a helpers.py with shared functions, and import from it the same way.
Built-in Modules#
- Python ships with dozens of built-in modules for common tasks: math for mathematics, os for talking to your operating system, random for randomness, and many more.
- You don't install these; they're simply there once Python itself is installed.
import math
import random
print(math.sqrt(64))
print(math.pi)
print(random.randint(1, 10))
Packages, pip, and PyPI#
- Built-in modules cover common needs, but for anything more specialized, like reading spreadsheets or talking to a web API, you'll reach for an external package.
- Packages live in a public repository called PyPI, the Python Package Index, and are installed with pip, Python's built-in package manager.
- From a terminal, 'pip install package_name' downloads and installs a package; 'pip uninstall package_name' removes it.
Mini Project 2: Automating a Spreadsheet#
- A very common real-world use of Python is automating repetitive spreadsheet work.
- We'll use openpyxl, an external package for reading and writing Excel files, installed with: pip install openpyxl
- Our spreadsheet, inventory.xlsx, lists products with a product number, an inventory count, a price, and a supplier, one row per product.
import openpyxl
workbook = openpyxl.load_workbook('inventory.xlsx')
sheet = workbook['Sheet1']
print(sheet.max_row)
print(sheet.max_column)
for row in range(2, sheet.max_row + 1):
product_number = sheet.cell(row, 1).value
inventory = sheet.cell(row, 2).value
price = sheet.cell(row, 3).value
supplier = sheet.cell(row, 4).value
print(product_number, inventory, price, supplier)
products_per_supplier = {}
for row in range(2, sheet.max_row + 1):
supplier = sheet.cell(row, 4).value
if supplier in products_per_supplier:
products_per_supplier[supplier] = products_per_supplier[supplier] + 1
else:
products_per_supplier[supplier] = 1
print(products_per_supplier)
low_stock = {}
for row in range(2, sheet.max_row + 1):
product_number = sheet.cell(row, 1).value
inventory = sheet.cell(row, 2).value
if inventory < 10:
low_stock[product_number] = inventory
print(low_stock)
for row in range(2, sheet.max_row + 1):
inventory = sheet.cell(row, 2).value
price = sheet.cell(row, 3).value
sheet.cell(row, 5).value = inventory * price
workbook.save('inventory_with_totals.xlsx')
print('Saved inventory_with_totals.xlsx')
Classes and Objects#
- Imagine an app with many users, where each user has an email, a name, and a job title, and can change their own password.
- A class is a blueprint describing what data and behavior something has. An object is one specific instance built from that blueprint.
- We define a class with the class keyword and a capitalized name.
class User:
def __init__(self, email, name, job_title):
self.email = email
self.name = name
self.job_title = job_title
def get_info(self):
return f'{self.name} works as a {self.job_title}. Contact: {self.email}'
def change_job_title(self, new_title):
self.job_title = new_title
user_one = User('alex@example.com', 'Alex', 'Data Analyst')
print(user_one.get_info())
user_one.change_job_title('Senior Data Analyst')
print(user_one.get_info())
user_two = User('sam@example.com', 'Sam', 'Product Manager')
print(user_two.get_info())
Connecting Classes#
class Post:
def __init__(self, message, author):
self.message = message
self.author = author
def get_post_info(self):
return f'"{self.message}" - posted by {self.author.name}'
new_post = Post('Just finished my first Python project!', user_two)
print(new_post.get_post_info())
Mini Project 3: Talking to a Web API#
- Two applications on the internet usually communicate over HTTP: your program sends a request to a URL, and gets a response back.
- The external requests package makes this easy in Python: pip install requests
- To keep this notebook fully self-contained and runnable offline, we'll spin up a tiny local demo server that responds exactly like a real API would, then query it with requests, exactly as you would query any real API on the internet.
import json
import threading
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
demo_projects = [
{'name': 'weather-dashboard', 'web_url': 'https://example.com/demo/weather-dashboard'},
{'name': 'expense-tracker', 'web_url': 'https://example.com/demo/expense-tracker'},
{'name': 'recipe-finder', 'web_url': 'https://example.com/demo/recipe-finder'},
]
class DemoHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(demo_projects).encode())
def log_message(self, *args):
pass
demo_server = ThreadingHTTPServer(('127.0.0.1', 0), DemoHandler)
demo_port = demo_server.server_address[1]
threading.Thread(target=demo_server.serve_forever, daemon=True).start()
print(f'Demo API running at http://127.0.0.1:{demo_port}')
import requests
response = requests.get(f'http://127.0.0.1:{demo_port}/api/v4/projects')
print(response.status_code)
print(response.text)
projects = response.json()
print(type(projects))
for project in projects:
print(f"{project['name']}: {project['web_url']}")
Wrap-Up: What You Learned#
- Core Python building blocks: variables, data types, string formatting with f-strings, functions, parameters, return values, and variable scope.
- Getting and validating user input with input, type conversion, if/elif/else, comparison operators, booleans, and try/except.
- Repetition and collections: while loops, for loops, lists, sets, and dictionaries.
- Organizing and reusing code with modules, built-in modules, and external packages installed through pip.
- Mini Project 1: a deadline countdown tool built with the datetime module.
- Mini Project 2: automated spreadsheet processing and reporting with openpyxl.
- Object-oriented programming: classes, objects, methods, and connecting classes together.
- Mini Project 3: talking to a web API with requests and parsing JSON responses.
- Practice prompt: pick one mini project and extend it, for example adding a new unit to the countdown tool, a new report to the spreadsheet script, or a new field to the User class.
- You went from print('Hello') to shipping three real projects in one sitting. That's rare. Subscribe so the next build shows up in your feed, no searching required.
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



