Skip to content

Lesson 05

Capstone — Build a Citation Generator

Tie Part 1 together by writing a tiny program that takes the bits of a citation — author, title, year, place — and prints out a properly formatted reference.

You’ve spent four lessons getting comfortable with Python’s basic data types. Strings hold text; integers and floats hold numbers; variables let you give them names. That’s enough to write something that earns its keep on a real research project.

This capstone builds a citation generator — a tiny program that takes the parts of a bibliographic entry and prints them out as a properly formatted reference. It’s the kind of helper a working researcher writes once and reuses for years.

Everything here uses only the types and operations from Lessons 02–04. No lists, dicts, loops, or functions yet — those come in the next parts.

What we’re building

A citation looks like this in MLA-ish style:

Voltaire. Candide. 1759. Paris.

Four pieces — author, title, year, place — strung together with the right punctuation. Easy to write by hand once. Annoying to write by hand fifty times. Computers exist for this.

A first cut

The simplest version is four variables and a print:

author = "Voltaire"
title = "Candide"
year = 1759
place = "Paris"

print(author + ". " + title + ". " + str(year) + ". " + place + ".")

Notice the str(year)year is an integer, and Python won’t concatenate an integer to a string. You have to convert. That’s the first gotcha you ran into in Lesson 04.

Cleaner with f-strings

Concatenation gets ugly fast. F-strings — string literals that splice in values — read better:

author = "Voltaire"
title = "Candide"
year = 1759
place = "Paris"

citation = f"{author}. {title}. {year}. {place}."
print(citation)

That’s the version you’d actually write. The f prefix turns the string into a template; anything inside {} is evaluated as Python and inserted.

Italicizing the title

Print can’t italicize, but a real citation often wraps the title in markdown asterisks or underscores. One line gets you there:

author = "Voltaire"
title = "Candide"
year = 1759
place = "Paris"

citation = f"{author}. *{title}*. {year}. {place}."
print(citation)

Now you have something you could paste into a Markdown document or a Jupyter notebook and have it render properly.

Computing the age of the work

The current year minus the publication year is the work’s age. That’s an integer subtraction:

author = "Voltaire"
title = "Candide"
year = 1759

current_year = 2025
age = current_year - year

print(f"{title} is {age} years old.")

Multiple authors

A book with two authors needs different formatting. Without lists yet, the trick is to keep two name variables and join them with a comma:

first_author = "Diderot"
second_author = "d'Alembert"
title = "Encyclopédie"
year = 1751

citation = f"{first_author} and {second_author}. *{title}*. {year}."
print(citation)

When you reach lists in Lesson 07, you’ll see a much cleaner way to handle “any number of authors.” For now, this is plenty.

Cleaning user-supplied text

Real input is messy. Authors might come in with stray spaces or inconsistent capitalization. Two string methods from Lesson 03 handle most of it:

raw_author = "  voltaire  "
raw_title = "candide"

author = raw_author.strip().title()    # "Voltaire"
title = raw_title.title()              # "Candide"

print(f"{author}. *{title}*.")

strip() removes leading/trailing whitespace; title() capitalizes the first letter of each word. They’re cheap insurance against inconsistent input.

Putting it together

Here’s the version that uses everything from Part 1 — string formatting, integer math, type conversion, and a touch of cleanup:

raw_author = "  voltaire  "
raw_title = "candide"
year = 1759
place = "Paris"
current_year = 2025

author = raw_author.strip().title()
title = raw_title.title()
age = current_year - year

citation = f"{author}. *{title}*. {year}. {place}."
print(citation)
print(f"This work is {age} years old.")

That’s a tiny but real program. Every line uses something you’ve learned. Nothing in it is fake — researchers really do write helpers like this for their own bibliographies, and they really do reuse them for years.

Try it yourself

Modify the program so it:

  • Prints the citation in two different styles (MLA and Chicago, say). What changes between them?
  • Handles a missing place — what do you want printed when place is the empty string?
  • Adds a translator field, but only includes it in the output if a translator is actually given.

The third one will push you toward conditionals — which is exactly what Part 3 introduces. Hold the question in mind; you’ll have the right tool for it shortly.

Where to next

Part 2 introduces data structures — tuples, lists, and dictionaries. These are containers for many values at once, and they unlock most of what the rest of the course can do. A citation generator that handles a hundred books at a time, instead of one, is a list-and-dict problem.

Continue to Lesson 06: Python Tuples.

Running the code

Save any snippet to a file — say cite.py — and run it from your project folder:

uv run cite.py

uv run uses the project’s Python automatically; no virtualenv to activate. If you haven’t set the project up yet, Lesson 01 walks through it.