Before layering on new ideas, let us lock in the essentials from Chapter 1. Python is dynamically typed, indentation marks blocks, and a script runs top to bottom. Your daily toolkit contains a few data types:
int (whole) and float (decimal), e.g. 42 and 3.14."model".[1, 2, 3].(1, 2).{"name": "Ada"}.A loop repeats work, and if/elif/else chooses between paths. Those building blocks combine into everything else in this book.
Lists are everywhere once you start modelling real data. A few common patterns show why they matter.
A stack is last-in, first-out: add with append, remove with pop() from the end. A queue is first-in, first-out: add with append, remove with pop(0) from the front.
tasks = []
tasks.append("clean data") # push
tasks.append("train model") # push
print(tasks.pop()) # pops "train model" - stack behaviour
A list of dictionaries stores rows, much like a mini table:
students = [
{"name": "Mira", "marks": 88},
{"name": "Leo", "marks": 71},
]
print(students[1]["marks"]) # 71
Lists help group related values and keep them in order. Sorting and reversing are built in:
scores = [45, 90, 60]
scores.sort()
print(scores) # [45, 60, 90]
scores.reverse()
print(scores) # [90, 60, 45]
A lambda is a tiny anonymous function written on one line. It has no def and no name; you simply give it parameters, a colon, and the expression to return:
square = lambda x: x * x
print(square(6)) # 36
Lambdas shine when you need a quick function as an argument to another function. If the logic is long or reused in many places, prefer a normal def for clarity.
if blocks or assignments. Use it for short, one-line jobs only.
map(func, iterable) applies a function to every item of a sequence and hands back the results. It is a one-liner replacement for a for loop that transforms a whole collection:
temps_c = [0, 20, 37]
to_f = lambda c: c * 9 / 5 + 32
temps_f = list(map(to_f, temps_c))
print(temps_f) # [32.0, 68.0, 98.6]
In Python 3, map returns a lazy iterator, so wrap it with list() when you want the materialised result.
filter(func, iterable) keeps only the items for which the function returns a truthy value. It is the one-liner way to select a subset:
numbers = [1, 2, 3, 4, 5, 6]
is_even = lambda n: n % 2 == 0
evens = list(filter(is_even, numbers))
print(evens) # [2, 4, 6]
Notice the symmetry: map transforms every element, while filter keeps or drops each element.
The real power appears when the three work together. The classic recipe is filter first, then map — select the items you care about, then transform them:
prices = [199, 50, 1200, 80, 900]
cheap = filter(lambda p: p < 500, prices)
double = map(lambda p: p * 2, cheap)
print(list(double)) # [398, 100, 160]
Read it out loud: "take prices below 500 and double them." Chains like this read like English and pack a whole loop into a single line.
Functions are the building blocks of every Python program. Here is how to write one properly, with defaults, returns, and documentation.
def greet(name):
return "Hello, " + name + "!"
def power(base, exponent=2):
return base ** exponent
print(power(3)) # 9 - exponent defaults to 2
print(power(3, 3)) # 27
def average(nums):
"""Return the arithmetic mean of a list of numbers."""
total = sum(nums)
return total / len(nums)
print(average([10, 20, 30])) # 20.0
The string right after def is the docstring. It documents what the function does and is visible via help(average).
is_palindrome(word) that returns True if a string reads the same forwards and backwards.taxed(amount, rate=0.18) that returns the total price including tax.describe(d) that takes a dictionary and returns a one-line summary of its keys and values.map and filter, write one-liners that: (a) keep the words in ["hi", "python", "ai", "code"] that are longer than 2 characters, and (b) capitalise them. Then rewrite the same logic with a plain for loop to confirm both versions agree.