livepython.net
CHAPTER 16Styling Your Code (PEP 8)
16.4  CLEAN CODE

Clean Code in Python: Habits Every Beginner Needs

One Statement per Line

Clean code is code that's easy to read, easy to change and hard to get wrong. The first clean-code habit is the simplest: write one statement per line. A statement is one complete instruction, like total = 0 or print(total).

Think of it like a shopping list. One item per line, and you can tick them off one by one. Write everything on one line, and you skip something.

The rules

  • Don't squeeze several statements onto one line with semicolons ;.
  • Don't put the block of an if, for, while or def on the same line as its colon. Start a new, indented line.
  • Compare a True/False value directly: write if is_open:, not if is_open == True: (chapter 8).

Avoid: squeezed lines

PYTHONedit me
a = 3; b = 4; print(a * b)
if a < b: print("a is smaller")
OUTPUT
12
a is smaller

Python allows both, but you have to read every character to find where one instruction ends. And it can break: an if can't come after a semicolon at all.

PYTHONedit me
marks = 72; if marks >= 40: print("Pass")
OUTPUT
SyntaxError: invalid syntax

Good: one line, one job

PYTHONedit me
marks = 72
if marks >= 40:
    print("Pass")
OUTPUT
Pass

Now your eye goes straight down the left edge: store, check, print. When an error happens, the line number points to exactly one instruction, so you know where to look.

Common beginner doubt: "Isn't shorter code better?" Fewer lines isn't the goal. Fewer ideas per line is. A program with 10 clear lines beats one with 3 crowded lines.

One statement per line, and every block on its own indented lines.

your turnFix the code

Fix the code so it prints: Pass

It should print: Pass

marks = 72; if marks >= 40: print("Pass")
This code does not work yet. Fix it, then press Run.
your turnPredict the output

What will this print?

x = 2; y = 5; print(x + y)
Your turn! What will this code show on the screen?

No Magic Numbers: Use Named Constants

A magic number is a number in your code with no name, so the reader can't tell what it means. The fix: give it a name, as an UPPER_CASE constant at the top of the program.

Think of it like a medicine bottle. "Take 2" leaves you guessing. "Take 2 tablets after dinner" tells you everything.

Avoid: what are 1.18 and 499?

PYTHONedit me
price = 600
if price > 499:
    price = price - 50
print(price * 1.18)
OUTPUT
649.0

Is 499 a limit? Is 50 a discount? What is 1.18? You'd have to ask whoever wrote it.

Good: every number has a name

PYTHONedit me
DISCOUNT_FROM = 500
DISCOUNT = 50
TAX_RATE = 0.18

price = 600
if price >= DISCOUNT_FROM:
    price = price - DISCOUNT
print(price + price * TAX_RATE)
OUTPUT
649.0

Same output, but now the code explains itself. And when the shop changes its tax rate, you change one line at the top, not every place 1.18 was hiding.

The rules

  • Give every number with a meaning a name: PASS_MARK = 40, HOURS_PER_DAY = 24.
  • Put the constants at the top, in UPPER_CASE (the Naming topic of this chapter).
  • Use the name everywhere, never the number again.
  • Numbers whose meaning is obvious don't need a name: count = 0, count += 1, total / 2 for half.

Common beginner doubt: "It's only used once. Does it still need a name?" Yes, if the reader can't tell what it means. The name is for understanding, not only for reuse.

If a number has a meaning, give it a name.

your turnFill the gap

Use the constant, not the number

LATE_FEE_PER_DAY = 5 days_late = 4 fine = days_late * ? print(fine)

It should print: 20

Which piece makes this code work?
your turnPick the right idea

Which number in this code is a magic number?

count = 0 for price in [300, 650, 800]: if price > 499: count += 1 print(count)
Think about it, then pick one.

Small Functions That Do One Job

A clean function does one job, and its name says which job. When you see the same lines copied two or three times, that's a sign: those lines want to be a function (chapter 15).

Think of it like the tools in a toolbox. A hammer hammers, a screwdriver turns screws. A tool that tries to do everything does each job badly.

Avoid: the same lines again and again

PYTHONedit me
print("Kitchen:", 3 * 4, "square metres")
print("Bedroom:", 4 * 5, "square metres")
print("Hall:", 5 * 6, "square metres")
OUTPUT
Kitchen: 12 square metres
Bedroom: 20 square metres
Hall: 30 square metres

Now say the shop wants "sq m" instead of "square metres". You'd have to change three lines, and it's easy to miss one.

Good: one function, called three times

PYTHONedit me
def print_room_area(room, length, width):
    """Print the floor area of one room."""
    area = length * width
    print(f"{room}: {area} square metres")


print_room_area("Kitchen", 3, 4)
print_room_area("Bedroom", 4, 5)
print_room_area("Hall", 5, 6)
OUTPUT
Kitchen: 12 square metres
Bedroom: 20 square metres
Hall: 30 square metres

The work is written once. A change goes in one place. Programmers call this DRY: "Don't Repeat Yourself".

The rules

  • One function, one job. If you need the word "and" to describe it, think about splitting it in two.
  • Start the name with a verb that says the job: print_room_area, get_average.
  • Keep functions short enough to see on one screen without scrolling.
  • Give each function a docstring (chapter 15) that says what it does.
  • Copied the same lines twice? Make a function.

Common beginner doubt: "Isn't one big block of code simpler?" At first, yes. But small named functions are like chapter titles: you can read the main program and understand it without reading every line inside them.

One job per function. If you copy code, make a function instead.

your turnOrder the lines

Put the lines in order to print the average: 80.0

  1. print(average)
  2. def get_average(marks):
  3. average = get_average([70, 80, 90])
  4. """Return the average of a list of marks."""
  5. return sum(marks) / len(marks)
These lines are mixed up. Put them back in order, then press Check.
your turnPredict the output

Remember join() from the Strings chapter?

words = ["clean", "python", "code"] print("-".join(words))
Your turn! What will this code show on the screen?

Comments That Explain Why

A good comment explains why the code does something. The code itself already shows what it does. You learned this in chapter 6. PEP 8 adds a few rules about how comments should look.

Think of it like a note on the fridge. "Milk" says what. "Buy oat milk, Lucky can't drink cow's milk" says why, and that's the part you'd never guess.

PEP 8 rules for comments

RuleGoodAvoid
a space after ## shop closes at 9#shop closes at 9
two spaces before an inline commenttotal = 0 # resettotal = 0 # reset
say why, not what# members pay less# subtract 20
keep it true when the code changesan old comment about old code
  • A comment on its own line is indented like the code below it.
  • Comment lines stay under 72 characters.
  • Functions explain themselves with a docstring (chapter 15), not a comment above the def.
PYTHONedit me
MEMBER_DISCOUNT = 20  # same for every item, so it's fair


def get_price(price, is_member):
    """Return the price after any member discount."""
    if is_member:
        # members pay less to thank them for joining
        price -= MEMBER_DISCOUNT
    return price


print(get_price(150, True))
OUTPUT
130

Avoid: comments that repeat the code

PYTHONedit me
count = 0  # set count to 0
count += 1  # add 1 to count
print(count)  # print count
OUTPUT
1

Every comment says what the code already says. They add reading, not understanding. Delete them, or say why.

Common beginner doubt: "More comments are always better, right?" No. With clear names (the Naming topic) and small functions, most lines need no comment at all. Save comments for the surprises.

Comments explain why, start with "# ", and sit two spaces after the code.

your turnPick the right idea

Which line follows PEP 8 and has the most helpful comment?

Think about it, then pick one.
your turnType the output

Remember comments from chapter 6?

# print("Hello") print("Bye") # print("Hi")
Read the code line by line, then type the output exactly.

Remove Dead Code Before You Finish

Dead code is code that never runs, or whose result is never used. It's the last thing to clean up before you call a program finished.

Think of it like your desk after a school project. The scraps, the old drafts and the pencil shavings helped while you worked. Before you hand the project in, they go in the bin.

Kinds of dead code

  • Commented-out code: old lines you switched off while testing (chapter 6).
  • Debug prints: lines like print("debug:", total) that helped you find a bug.
  • Unused variables: values you stored but never use.
  • Code after return: a function stops at return, so lines below it in the same block never run.
PYTHONedit me
def get_discount(price):
    return price * 0.1
    print("Discount ready")


print(get_discount(500))
OUTPUT
50.0

Discount ready is never printed. It sits after return, so it's dead. A reader might think it runs, and that's the danger: dead code tells lies.

The rules

  • Delete commented-out code and debug prints when the program works.
  • Delete variables nobody uses.
  • Never put code after return in the same block.
  • After you rename or delete something, run the program again. A leftover old name gives a NameError, and that's a clue, not a disaster.

Common beginner doubt: "What if I need that old code again later?" Then you'll write it again, better. In real projects, a tool called version control (like Git) keeps every old version for you, so deleting is safe.

Before you finish, delete code that never runs or is never used, then run it once more.

your turnPredict the output

What will this print?

def double(n): return n * 2 print("Doubled!") print(double(4))
Your turn! What will this code show on the screen?
your turnSpot the bug

Which line breaks?

One line stops this program. Tap it.

Practice: Clean code

Solve these to lock in what you learned in this topic. Each one runs in your browser.

  1. 147.Python Program to Replace Magic Numbers with Named ConstantsEasySolve
  2. 148.Python Program to Replace Repeated Code with a FunctionMediumSolve
  3. 149.Python Program to Clean Up a Messy Report CardHardSolve