Decode this, and the software world is yours!

Three questions solve any Python task. Watch them work on two numbers, 2 and 3.

1

The method

Read the notes for this step ↓

Study notes: every step explained in detail

One card for each of the 8 steps, with a real-time scenario and a worked example. Click a card’s heading to play that step in the animation above.

In simple words

Beginners often open the editor, start typing and get stuck. Experienced developers do something else first: they answer three questions. What data do I have? What must happen to it? How should I pack the code, as a function or as a class? The three answers are the plan, and with a plan the typing is the easy part. The same three questions work for a two-line exercise and for a large project.

Real-time scenario

Your team lead says: "Tell me the total of today’s paid orders." Before writing any code, you answer the three questions. Data: a list of orders, each with a status and an amount. Operation: go through every order, keep the paid ones and add their amounts. Design: it is one task, so one function is enough. After that, the code almost writes itself.

Common mistake

Typing first and thinking later. If you cannot say the three answers in plain English, you are not ready to write the code.

The three questions

QuestionWhat you decideFor "total of paid orders"
1. What do I have?The data: where it comes from, one value or many, and its typeA list of orders; each order is a dictionary
2. What do I do with it?The operationRepeat, compare, calculate
3. How do I pack it?The design: a function or a classOne function

Example

# 1. Data: what do I have?
orders = [{"id": 101, "status": "paid", "amount": 300},
          {"id": 102, "status": "refunded", "amount": 150},
          {"id": 103, "status": "paid", "amount": 200}]

# 2. Operation: repeat, compare, calculate
# 3. Design: one task, so one function
def paid_total(orders):
    total = 0
    for order in orders:
        if order["status"] == "paid":
            total = total + order["amount"]
    return total

print(paid_total(orders))        # 500

In simple words

Data is whatever the program works on. Ask three things about it. Where does it come from: written in the code, typed by a user, or read from a file, a database or an API (a web address that returns data)? Is it one value or many? What type is it? One value is an int (a whole number), a float (a decimal number), a str (text) or a bool (True or False). Many values go in a list, a tuple, a set or a dictionary. The type matters because it decides what you are allowed to do: two numbers can be added, but a number and a piece of text cannot.

Real-time scenario

A customer types a quantity into a form on the shop’s website. It looks like the number 2, but everything typed into a form arrives as text: "2". If the program multiplies it by the price without converting it first, the result is wrong or the program stops with an error. Checking the type first prevents this.

Common mistake

Assuming the type. When you are not sure, print type(value) and look.

Data in an online shop

The dataExampleType
Quantity2int: a whole number
Price149.50float: a decimal number
Customer name"Ravi"str: text
Is it paid?Truebool: True or False
Items in a cart["pen", "book"]list: many values, in order
One order{"id": 101, "amount": 300}dict: names paired with values

Example

a = 2
b = 3
print(type(a))                   # <class 'int'>

quantity = input("Quantity: ")   # the customer types 2
print(type(quantity))            # <class 'str'>: text, not a number

quantity = int(quantity)         # convert it before doing maths
print(quantity * 149.50)         # 299.0

In simple words

An operation is what happens to the data. Almost everything a program does is one of five kinds: calculate, compare, combine conditions, check whether something is present, and repeat for every item. Large programs are these five, mixed together. To find the operation, say the task in plain English first; each verb in your sentence points to one of the five.

Real-time scenario

The shop gives free delivery when an order is above 500 and the city is one it delivers to. In plain English: add the item prices (calculate), see whether the total is above 500 (compare), see whether the city is in our list (check), and both must be true (combine). To add the prices, the program goes through the cart one item at a time (repeat).

Common mistake

Confusing = with ==. One equals sign stores a value in a name; two equals signs compare two values.

The five kinds of operation

KindSymbolsShop example
Calculate+ - * /price * quantity
Compare== != > <total > 500
Combineand or nottotal > 500 and city_ok
Checkincity in delivery_cities
Repeatforfor price in prices

Example

prices = [300, 150, 200]
city = "Hyderabad"
delivery_cities = ["Hyderabad", "Chennai", "Pune"]

total = 0
for price in prices:             # repeat
    total = total + price        # calculate

# compare, check and combine in one line
free_delivery = total > 500 and city in delivery_cities
print(total, free_delivery)      # 650 True

In simple words

A function is a named piece of code that does one task. You hand it data through its parameters, which are the names inside the brackets. It does the work and hands back a result with return. When it finishes, it remembers nothing: the next call starts fresh. You write it once and use it wherever that task is needed.

Real-time scenario

The shop adds 18% GST to prices in ten places: the product page, the cart, the invoice and several reports. If the calculation is copied ten times, a change in the rate means ten edits, and one of them will be missed. With a function, the rule lives in one place and every page calls it.

Common mistake

Using print inside the function where return is needed. print only shows the value on the screen; return gives it back, so that the rest of the program can use it.

Reading a function

PartIn the exampleMeaning
defdef addition(a, b):Starts the function and gives it a name
Parametersa, bThe data the function receives
returnreturn a + bThe result it hands back
The calladdition(2, 3)Runs the function with real values

Example

def addition(a, b):
    return a + b

result = addition(2, 3)
print(result)                    # 5

# the same design for a real task
def price_with_gst(price, rate=18):
    return price + price * rate / 100

print(price_with_gst(100))       # 118.0
print(price_with_gst(250))       # 295.0

In simple words

A class is a design for objects that keep data and the functions that work on that data together. The special function __init__ runs once, when the object is created, and stores the values. The word self means the object itself, so self.a means "this object’s own a". A function written inside a class is called a method. You create an object from the class, and then call its methods.

Real-time scenario

An order in the shop has an ID, a list of items and a status. Many things are done to it: calculate its total, add GST, mark it as paid, print its invoice. Every one of these needs the same order data. A class keeps that data in one place, and each method reads it from self.

Common mistake

Forgetting self. Writing a + b inside a method fails, because a and b live on the object; write self.a + self.b.

Five words to know

WordMeaning
classThe design, written once
objectOne thing built from the design, such as cal
__init__Runs once and stores the data
selfThis object’s own data
methodA function inside a class

Example

class Calculator:
    def __init__(self, a, b):
        self.a = a               # store the values once
        self.b = b

    def addition(self):
        return self.a + self.b

    def subtraction(self):
        return self.a - self.b

cal = Calculator(2, 3)           # __init__ runs here
print(cal.a, cal.b)              # 2 3

In simple words

Once the values are stored in the object, every method can use them, and you do not pass them again. Each object also has its own data: two objects made from the same class do not disturb each other, although they share the same code.

Real-time scenario

Two customers are shopping at the same moment. Each has a cart object of their own. Adding a pen to one cart does not change the other cart, yet both carts run the same code.

Common mistake

Passing the same values into every method again. If the data is stored on the object, read it from self.

Example

# Calculator is the class from step 5
cal = Calculator(2, 3)
print(cal.addition())            # 5
print(cal.subtraction())         # -1    (2 - 3)

other = Calculator(10, 4)        # a second object, with its own data
print(other.addition())          # 14
print(cal.addition())            # 5: unchanged

# the same idea in the shop
class Cart:
    def __init__(self):
        self.items = []

    def add(self, name, price):
        self.items.append((name, price))

    def total(self):
        return sum(price for name, price in self.items)

ravi = Cart()
ravi.add("pen", 20)
ravi.add("book", 150)
print(ravi.total())              # 170

In simple words

The rule is short. One task needs a function. Several tasks on the same data need a class. Do not begin with a class for everything. Begin with functions, and when you notice three or more functions passing the same data to each other, that data belongs in a class.

Real-time scenario

These are the three tasks on the tray in the animation. "Add two numbers" is one task, so it is a function. "Total of paid orders" is also one task, so it is a function. "Load, clean, total and save a report" is four steps that all work on the same orders, so it is a class.

Common mistake

Writing a class that has only one method. That is a function in disguise; write a function.

Three tasks, sorted

TaskDesignWhy
Add two numbersFunctionOne task; nothing to remember
Total of paid ordersFunctionOne task; data in, one number out
Load, clean, total and save a reportClassFour steps share the same orders

Example

# one task: a function
def paid_total(orders):
    return sum(o["amount"] for o in orders if o["status"] == "paid")

# several tasks on the same data: a class
import csv

class OrdersReport:
    def __init__(self, path):
        self.path = path
        self.orders = []

    def load(self):
        with open(self.path, newline="") as f:
            self.orders = list(csv.DictReader(f))

    def clean(self):
        self.orders = [o for o in self.orders if o["status"] == "paid"]

    def total(self):
        return sum(float(o["amount"]) for o in self.orders)

    def save(self, out_path):
        with open(out_path, "w") as f:
            f.write(f"paid total: {self.total()}\n")

report = OrdersReport("orders.csv")
report.load()
report.clean()
report.save("report.txt")

In simple words

The same three questions work on any task, at any size. A large program is many small pieces, and each piece is found by asking the three questions again. Practise on small tasks until asking them becomes a habit.

Real-time scenario

An interviewer says: "Write a program to find the customer who spent the most." Answer aloud before you write anything: "The data is a list of orders, each with a customer and an amount. The operation is to go through the orders, add each amount to its customer’s total, and then compare the totals. It is one task, so I will write a function." A clear spoken plan like this often counts for more than the code.

Common mistake

Thinking the method is only for beginners’ exercises. Senior engineers ask the same three questions; their data and their designs are simply bigger.

Three tasks to practise on

TaskDataOperationDesign
Count the vowels in a wordOne strRepeat, check, calculateFunction
Find the largest of three numbersThree intsCompareFunction
A bank account with deposit, withdraw and balanceOne balance, changed by several actionsCalculate, compareClass

Example

orders = [{"customer": "Ravi", "amount": 300},
          {"customer": "Asha", "amount": 150},
          {"customer": "Ravi", "amount": 200}]

def top_customer(orders):
    totals = {}
    for order in orders:                          # repeat
        name = order["customer"]
        totals[name] = totals.get(name, 0) + order["amount"]   # calculate
    return max(totals, key=totals.get)            # compare

print(top_customer(orders))      # Ravi