A step-by-step introduction with no programming prerequisites
Start from zero: explain, run, change, and check.
Prof. Xuhu Wan
ISOM, HKUST Business School · 2026 Edition
No programming background is needed. We start with familiar school and everyday examples.
int, and floatstr, conversion, and f-stringsiffor, and condition-controlled while loopsChapter 1–4 build on these basics for second-year business-school students.
For each example:
Practice cells wait for you to click Run. Edit the code, not the output. These examples run in the browser; no Python installation is needed.
The Chapter 0 book follows the same examples with extra explanations.
Python is a programming language: we write instructions, and Python follows them.
print(...) means show this on the screen. The parentheses hold what we want to show. Matching quotes mark text.
Expected output: Hello, Python! — without the quotation marks. Change the message to your own greeting.
Numbers do not need quotes. Text does. Python calculates the expression before print() displays it.
The outputs are 2 + 3, 5, and Answer: 5.
The comma lets print() show more than one value, separated by a space. Try replacing 3 with 8.
A variable is a name that refers to a value. A useful name tells us what the value means.
Read pocket_money = 100 as: make the name pocket_money refer to 100. = is assignment, not an equation to solve.
Python first calculates the right side of =, then assigns the result to the name on the left. The output is 75.
Names are case-sensitive: price and Price are different. Use names such as snack_cost; do not start a name with a digit.
A name can be assigned again. The new value replaces what the name previously referred to.
Outputs: 10, then 15. In the update, Python reads the old 10, adds 5, and assigns 15.
points = points + 5 makes sense as an instruction, even though it would not make sense as an algebraic equation.
A calculated value remembers the result of that calculation. It does not automatically recalculate when an input changes.
Outputs: 20, then 24. We must run the calculation again to use the new price. Rerunning this whole cell starts again at price = 10.
Start with HK$100, receive HK$20, then spend HK$35. Finish the two updates.
Expected result: Money left: 85. Then start with 50 instead of 100; the result should be 35.
A type tells Python what kind of value it is working with. The value has the type; the variable name can be reassigned.
| Python name | Meaning | Example |
|---|---|---|
int |
Integer: a whole number | 4 |
float |
An approximate decimal number | 12.5 |
str |
String: text | "hello" |
type(value) asks Python to tell us the type.
Outputs include <class 'int'>, <class 'float'>, and <class 'str'>. Read these as “integer”, “float”, and “string”. We will practise each type separately.
int is short for integer. Integers include positive whole numbers, zero, and negative whole numbers. Use them for counts such as students or tickets.
Outputs: 28, the type int, then 1000 1000.
An underscore makes a large number easier to read: 1_000 and 1000 have the same value. Use it instead of a thousands comma in a number literal.
A float represents an approximate number, often written with a decimal point. Use examples such as prices, lengths, and rates.
Outputs start with 12.5 and 50.0. Python need not display trailing zeros.
4 is an int; 4.0 is a float. A float can represent a whole-number value too. Here multiplying an int by a float produces a float.
+ adds two numbers. - subtracts the second number from the first. A leading minus sign makes a number negative.
Expected outputs: 9, 5, -5, 3.5, -2.
Predict 10 - 4 + 2, then add a line to check it. Addition and subtraction at this level are evaluated from left to right.
Use * for multiplication and / for division. Python does not use the written symbols × and ÷ as operators.
Outputs: 14, 3.5, 4.0, and the type float.
Dividing these built-in numeric types with / produces a float, even when the answer is a whole number. Dividing by zero raises ZeroDivisionError.
A power means repeated multiplication for a positive whole-number exponent.
2 ** 3 means 2 × 2 × 2. The first number is the base; the second is the exponent.
Outputs: 8, 8, 25, 1.
Use two asterisks together: **. The symbol ^ is a different Python operator and does not mean power. Try 3 ** 2 and 2 ** 3: do they give the same result?
Suppose 7 biscuits are shared into groups of 2. We can make 3 complete groups, with 1 biscuit left.
Outputs: 3.5, 3, 1, 7.
For nonnegative whole-number counts, // gives the number of complete groups and % gives the remainder. More generally, // takes the floor: -7 // 2 is −4, not −3. Here % is not a percentage sign.
Python uses the usual arithmetic order: powers, then multiplication/division, then addition/subtraction. Parentheses ask Python to do a group first.
Outputs: 14, 20, 18, 36. Write out the steps on paper.
Use parentheses when they make your intended calculation clearer. These examples use positive bases; write (-3) ** 2 when the negative sign belongs to the base.
There are 23 items. Each box holds 5. Use // and % to calculate the number of full boxes and the items left.
Expected: 4 full boxes, 3 items left, and 23 accounted for. Test 25 items: 5 full boxes, 0 left. Test fewer items than one box can hold.
str is short for string: a sequence of characters. Characters can be letters, spaces, digits, or symbols. Matching single or double quotes create text.
The quoted "250" is text even though its characters look like a number. The last line shows str and int. Quotes tell Python how to interpret what you wrote.
With numbers, + performs addition. With strings, + joins the text, called concatenation.
Outputs: 350, 100250, Hello, Alex, hahaha.
String multiplication by an integer repeats the text. Python does not silently guess how to add a number to a string: 100 + "250" raises TypeError.
An f-string is a string with an f just before the opening quote. Put a value or expression inside {...} to insert its result into the text.
Without f: Hello, {name}. With f: Hello, Alex.
The last line prints age 17. An f-string produces text; f is a prefix, not a separate variable you need to define.
A format instruction follows a colon inside the braces. :.2f means display a number with two digits after the decimal point.
Outputs: Price: HK$12.50, the type str, then 12.5 and float.
Formatting creates a readable message. It does not change the value or type of price. Try price = 12.567: the label displays HK$12.57 while the stored value remains 12.567.
Text from a form can look numeric. Conversion creates a value of a different type: use int() for whole-number text and float() for decimal text.
Outputs: 50.0 and 250 dollars. str() converts a value to text.
Choose the conversion to match the data: int("12.50") fails; float("12.50") works. int(3.9) gives 3, because it truncates toward zero rather than rounding.
A form returns the price and quantity as text. Convert the price with float() and the quantity with int(), then calculate the bill.
Check your result
Expected types: float, int. Expected bill: HK$50.00. Then change the inputs to "18.75" and "3"; the bill should be HK$56.25.
A method is an operation called after a value with a dot. name.upper() means “make an uppercase version of this text”. Parentheses call the method.
.strip() removes surrounding spaces; .upper() changes letter case. The combined result is HKUST CAFE.
These methods return new text. The original name still has its spaces and lowercase letters. .lower() makes a lowercase version.
Edit clean_name to remove surrounding spaces and convert the name to uppercase. Try a second input with different spaces and case.
Check your result
Use .strip() and .upper(). Expected output: Clean label: [HKUST CAFE], with no spaces next to the brackets. Test different surrounding spaces too.
Revenue is money from sales. Cost is money spent in this example. Profit = revenue − cost. Margin = profit ÷ revenue.
Profit is HK$370,000; margin is 29.6%. :, displays thousands commas. :.1% displays a fraction as a percentage with one decimal place.
We have not specified which expenses cost includes. The example does not establish a real company’s gross or net margin.
A comparison asks a yes/no question. Its answer has type bool, short for Boolean: True or False, with capitals and no quotes.
Outputs: False, True, True, False, then bool.
> means greater than; >= means greater than or equal; == means equal; != means not equal. Similarly, < means less than and <= includes equality.
= gives a name a value. == asks whether two values are equal. They do different jobs.
Outputs: 70, True, True, False. An int and a float can compare numerically equal. The text "4" and the integer 4 are different values.
Do not put quotes around Boolean values: "False" is text, not the Boolean False.
Use and when both conditions must hold. Use or when at least one must hold. not reverses a Boolean result.
Outputs: False, True, True.
Change has_student_card to True and predict all three results before running again. We use Boolean inputs here; these examples are yes/no decisions.
Approve a classroom screen only if price > 50 AND volume > 1,000,000. Define both comparisons and combine them. Then change volume to 5,000,000.
Check your result
With the first inputs, the three results are True, False, False. After increasing volume, all three should be True.
Set cost so that profit exceeds HK$420,000. Find the exact boundary first: does cost = 830,000 pass?
Check your result
The condition is strict: cost must be below 830,000.
if runs its indented instructions when a condition is true. else runs its instructions otherwise. The colon : starts a block.
At 65 the output is Pass, then Check finished. Try 59 and exactly 60.
These are classroom thresholds. The last line is not indented, so it runs after either branch.
Indentation means spaces at the start of a line. Use four spaces for instructions inside a block. Lines aligned at the same level belong to that level.
At False, only Leave home prints. Change to True: all three messages print.
The first two messages belong to if; the last does not. Missing indentation after a block header raises an indentation error.
Important
Each condition is checked in order; the first true branch runs and the rest are skipped. The else catches everything that wasn’t matched above.
These thresholds are a teaching example, not the course grading policy. If score >= 70 comes first, all scores of 70 or above enter C; 50 still enters F.
This code runs, but its overlapping conditions are in the wrong order. Fix the order and test scores 95, 82, 70, and 69.
Check your result
Expected grades: A, B, C, F. Put the highest threshold first.
A list keeps several values in order. Use square brackets [...] and commas between items.
Outputs: [70, 80, 90], 3, 240.
len(scores) counts the items. sum(scores) adds these numeric items. Add a fourth score and check both results. Next we learn how to read, change, and search a list before using loops.
An index is an item’s position. Python starts counting positions at 0, not 1. Square brackets after the list name select an item.
| Item | 70 | 80 | 90 |
|---|---|---|---|
| Index | 0 | 1 | 2 |
Outputs: 70, 90, [70, 85, 90]. Index -1 selects the last item. Assignment to scores[1] replaces the second item; the list length stays three.
For this list, index 3 is outside the list and raises IndexError. Predict the result if you replace the first item with 75.
A method is an operation belonging to an object. Read scores.append(90) as “ask the scores list to add 90”. The dot connects the list to its method; parentheses supply the input.
Outputs: [70, 80, 90], then [70, 80, 90, 85, 95]. append adds one item; extend adds each item from another list.
Outputs: [70, 80, [85, 95]], then 3. Here the added item is itself a list. Use extend when you want the two scores as separate items.
insert(index, value) puts a new item before the item currently at that index. Existing items move to make room; no item is replaced.
Outputs: [70, 80, 90], then [60, 70, 80, 90]. Index 0 means the front. Compare inserting at index 1 with assigning scores[1] = 80: insertion increases the length, while assignment does not.
Try inserting 95 at the end using index len(scores).
remove(value) deletes the first matching value. pop(index) deletes the item at a position and returns the removed value. With no index, pop() takes the last item.
Outputs: [80, 70, 90], Removed: 90, [80, 70], Removed: 80, [70]. The second 70 survives remove(70) because only the first match is removed.
remove raises ValueError if the value is absent. pop raises IndexError if the position is invalid or the list is empty. These methods change the list itself.
count(value) tells us how many matches there are. index(value) gives the position of the first match. value in scores tests whether the value is present and gives True or False.
Outputs: 2, 0, 0, False, Position of 90: 3. Zero matches is a valid count. An absent value has no index: index(100) would raise ValueError.
The final if checks membership before looking up the position. Change the searched value to 100 and observe that the indented print is skipped.
sort() puts comparable items in ascending order. reverse() flips the current order; it does not sort the items first.
Outputs: Reversed: [70, 90, 60, 80], Ascending: [60, 70, 80, 90], Descending: [90, 80, 70, 60].
These methods change the existing list and return None, meaning no result value. Use scores.sort() followed by print(scores); assigning scores = scores.sort() would make the name refer to None.
copy() makes a new outer list. For our lists of numbers, changing one copy’s items does not change the other. In contrast, alias = scores gives the same list another name.
Outputs: Scores: [70, 80, 90], Alias: [70, 80, 90], Backup: [70, 80], Cleared backup: [], Scores still: [70, 80, 90].
clear() removes all items from that list. Copying a list containing other lists is a shallow copy: its inner lists are still shared. We use simple number lists here.
| Method | What it does |
|---|---|
append(value) |
Add one item at the end |
extend(values) |
Add the individual items from another list |
insert(index, value) |
Add an item before a position |
remove(value) |
Delete the first matching value |
pop(index) / pop() |
Delete and return an item / the last item |
count(value) |
Count matching values |
index(value) |
Find the first matching position |
sort() |
Sort the existing list |
reverse() |
Flip the current order |
copy() |
Return a shallow copy |
clear() |
Empty the existing list |
len(scores) and sum(scores) are built-in functions, not list methods. Operations that only change the list return None; pop, count, index, and copy return useful results.
A loop repeats instructions. Read for score in scores: as “for each item in scores, call it score and run this block”.
Outputs: Score 70, Score 80, Score 90, then Done.
The indented line runs once per item, in list order. The unindented line runs after the loop finishes. You choose the item name; it need not be score.
Start the total at zero. On each visit, add the current item to the previous total.
Running totals: 70, 150, 240. Final total: 240.
For this numeric update, total += score is a shorter way to write total = total + score. Starting total inside the loop would reset it on every visit.
An average is the total divided by the number of items. Five prices add to 506, so their average is 506 ÷ 5 = 101.2.
Once we understand the steps, sum(prices) / len(prices) gives the same result. The list must be nonempty; dividing by its zero length would fail.
The loop computes a total. Edit the average calculation, then add one more price and rerun. The denominator must adapt to the list length.
Check your result
The first average should be 101.2. Divide by len(prices), not a fixed number.
range(start, stop) supplies integers from start up to, but not including stop. Use it for numbered repetitions.
The first loop visits 1, 2, 3. The second visits 0, 1, 2: with one input, range() starts at zero.
To visit years 1 through 4, use range(1, 5). Try the endpoint 4 and see which year disappears.
A while loop checks a condition before each repetition. If the condition is True, it runs the indented body and checks again. If the condition is False, it continues after the loop.
Outputs: Tickets left: 3, Tickets left: 2, Tickets left: 1, Finished. The body changes the value used in the condition. At zero, tickets_left > 0 becomes false.
This is called indefinite repetition: a condition controls when to stop, so we do not have to choose the repetition count in advance. It does not mean “run forever”. Try starting at zero: the body runs zero times and only Finished appears.
We have HK$70, save HK$15 per day, and stop when the balance reaches at least HK$100. Count the days as the loop runs; no day count is supplied to the loop.
Outputs: Day 1: HK$85.00, Day 2: HK$100.00, Days needed: 2.
| Check before the next repetition | Condition | Action |
|---|---|---|
| Balance 70 | 70 < 100 is True |
Save 15 |
| Balance 85 | 85 < 100 is True |
Save 15 |
| Balance 100 | 100 < 100 is False |
Leave the loop |
Assume daily_saving is positive. Change the goal to 115 and predict the days needed. If the starting balance already meets the goal, the answer is zero days. This model has no interest or spending.
The condition can depend on the current list length. Each pop() removes an item, so the list eventually becomes empty.
Outputs: Removed: 90, Items left: 2, Removed: 80, Items left: 1, Removed: 70, Items left: 0, Finished: [].
pop() takes the last item, so the removal order is 90, 80, 70. Checking the length before each removal prevents popping from an empty list. Try starting with scores = []; no item is removed.
Use for to visit a collection or a range. Use while when the next repetition depends on a condition. Both can produce the same output.
Both print Day: 1, Day: 2, Day: 3. The for loop gets its next item from the range. In the while loop, our code updates day.
For “visit every score”, choose for. For “keep saving until the goal is met”, choose while. A colon ends either loop header, and indentation marks its body.
An infinite loop keeps repeating without reaching a stop. In this unfinished sketch, count stays at 1, so the condition stays true:
The sketch is text, not an executable Python box. Run the corrected version:
Outputs: 1, 2, 3, Stopped at: 4. The update belongs inside the loop. It moves the value toward making the condition false; subtracting 1 here would move in the wrong direction.
Before running a while loop, explain its starting value, condition, update, and stopping case. For the savings example, zero or negative daily saving would not reach a higher goal.
A function is a named set of instructions. def defines it. Calling its name with parentheses asks Python to run it.
Outputs: 6, 20. number is a parameter: a name for the input inside the function. In double(3), the input 3 is an argument.
Defining the function does not run its body. Each call supplies an input and runs the calculation.
return sends a value back to the code that called the function. print() displays a value on the screen. They are different jobs.
Outputs: 105.0, 115.0. We can store and reuse the returned number. The 5% tax is an invented classroom example.
return ends that function call. A function that reaches the end without returning a value gives back None, Python’s “no value” marker.
A function can take more than one input. In these calls, Python matches the inputs to the parameters from left to right.
Outputs: 100, 60, 100. The last call labels its inputs explicitly.
The names inside the function refer to the inputs for that call. Define the function before calling it.
The area of a rectangle is length × width. Complete the function, then test more than one pair of inputs.
Expected areas: 15 and 10.0. Also test width = 0; the result should be zero. Both lengths must use the same unit.
A share is a unit of ownership. Selling shares gives gross proceeds: price × shares. A commission is a transaction fee.
Outputs: 1000, 1.0, 999.0. A rate of 0.001 means 0.1%. Next, put these steps into a reusable function. We assume a fixed sale price and this fee only.
Note
A function packages logic for reuse. Test representative inputs and check it again when its logic or assumptions change. Here we assume a fixed sale price and only a 0.1% commission.
Finish the function to deduct gross * commission_rate. Test both a zero fee and a 0.1% fee using the same function.
Check your result
Expected values: $1,000.00 and $999.00. Changing the fee input should change only the fee deduction.
7% means 7 out of 100: write it as 0.07 in a calculation. A balance grows by adding 7% of its current value.
Outputs: 700.0, 10700.0, 10700.0. Multiplying by 1 + rate combines the original balance and the increase.
For a 5% decrease use −0.05, so the multiplier is 0.95. These are assumptions for a calculation.
Suppose HK$10,000 grows at a constant 7% each year for four years. Each year grows the updated balance, so we multiply by 1.07 four times.
The result is HK$13,107.96. :,.2f combines thousands commas and two decimal places.
This is a hypothetical calculation, not a forecast. Fees, taxes, inflation, and changing annual returns are omitted.
A loop lets us see how the same calculation develops. The new balance becomes the starting balance for the next year.
Expected balances: 10,700.00 → 11,449.00 → 12,250.43 → 13,107.96.
years + 1 includes year 4 because the range endpoint is excluded. The formula and loop agree to the cent.
Repeat the calculation under three assumed constant annual growth rates. A negative rate reduces the balance.
At −5%: HK$8,145.06. At 0%: HK$10,000.00. At 7%: HK$13,107.96.
These are scenarios, not probabilities or a forecast range. The code applies our assumptions; it does not prove the assumptions will happen.
Replace the loop update so each annual return changes the current balance. Print the balance after each year. Does a negative year reduce it?
Check your result
Multiply the current balance by 1 + rate. Expected balances: 10,700.00; 10,165.00; 10,469.95; 10,469.95.
An error message tells us why Python could not follow an instruction. Read its final line, then find the relevant code.
| Error | Typical cause | First check |
|---|---|---|
NameError |
A name has not been defined | Spelling and run order |
TypeError |
The operation does not fit the types | type(...) and conversions |
SyntaxError |
Code is not valid Python | Quotes, parentheses, colons |
IndentationError |
A block is not indented correctly | Spaces at line starts |
A wrong answer can also occur without an error message. Compare outputs with small examples you can calculate by hand.
Run this cell to see an intentional error. We want numeric addition, giving 350. Convert the numeric text before adding it.
Expected first run: TypeError. Expected after your fix: 350.
Use int(online_sales_text) for this whole-number input. Test "0" and "50" too. A nonnumeric value such as "unknown" cannot be converted this way.
Vague prompt: “Fix this code.”
Specific prompt:
My code is
revenue = 100 + "250". It raises a TypeError about adding an int and a str. I expected the integer 350. Explain the error and suggest a fix.
int("250") is appropriate for this input."250.50" or "unknown".A program can run successfully and still answer the wrong question. Check assumptions, units, and results as well as errors.
Warning
On 23 Sep 1999 NASA lost the Mars Climate Orbiter after a navigation error sent it too close to Mars.
Ground software reported thruster impulse in pound-force seconds (lbf·s); the interface specification required newton seconds (N·s). The navigation software treated the values as if they met that specification.
The documented units were not followed, and verification was inadequate. Clear names help, but they do not replace checking the data and conversion.
revenue_hkd, not revenue.In this course, use a short memo to connect a calculation to a decision. State what the evidence supports and what remains uncertain.
To: Future Me
From: An ISOM 2600 student
Subject: Test the assumptions behind a four-year savings projection
Recommendation: Compare growth scenarios before choosing how to use the savings.
Evidence: HK$10,000 becomes HK$8,145.06 at −5%, HK$10,000.00 at 0%, or HK$13,107.96 at 7% annual growth for four years.
Caveats: These are assumed constant rates, not forecasts. Fees, taxes, and inflation are omitted.
Next step: Check when the money is needed and model changing annual returns and relevant costs.
| Code | Meaning |
|---|---|
x = 4 |
Make x refer to 4 |
int, float, str, bool |
Whole number, approximate number, text, yes/no |
type(x) |
Inspect the type |
+ - * / |
Add, subtract, multiply, divide |
** // % |
Power, floor division, remainder |
int("4"), float("4.5") |
Convert numeric text |
f"{price:.2f}" |
Make text displaying two decimal places |
== != < > <= >= |
Compare values |
Display formatting and numeric rounding are different. round(x, n) returns a rounded value; it is a detail to consult when a task needs it.
| Code | Meaning |
|---|---|
and, or, not |
Combine or reverse Boolean conditions |
if / elif / else |
Choose a branch |
[70, 80, 90] |
A list in order |
len(scores), sum(scores) |
Count items, add numeric items |
scores.append(95), scores.pop() |
Add an item, remove and return the last item |
for score in scores: |
Visit each item |
range(1, 5) |
Integers 1 through 4 |
while balance < goal: |
Repeat while a condition is true |
def double(number): |
Define a function with an input |
return number * 2 |
Send a result back |
Indentation shows which instructions belong to a branch, loop, or function.
Can you explain and check these without guessing?
4, 4.0, and "4" differ?7 / 2, 7 // 2, and 7 % 2 give different results?"2" + "3" not 5? How can you make numeric 5?append, extend, and insert differ?pop, and what is returned by sort?while loop stop, and can its body run zero times?return different from print()?Next: Chapter 1 deepens lists, then introduces pandas Series, NumPy, statistics, and plots for second-year business-school students.
Prof. Xuhu Wan · HKUST ISOM · Introduction to Business Analytics
Comments and Reading Order
Python normally runs these lines from top to bottom.
A
#starts a comment: a note for people reading the code. Python ignores the rest of that line.Expected output:
30. Changing a comment does not change the calculation; changingpricedoes.