Product Dojo is a members' platform. Sign in to open the lessons, clear
stages, and earn the certificate for each one. Your rank and credentials
stay with your account across every device you use.
Free to join, through GitHub, Google or LinkedIn. No password to set.
Not unlocked yet
Stages open in order. Clear the one before this to come back here.
Until now your programs have known everything in advance. The moment they can
ask a question, the same twelve lines work for any answer — and one specific
trap accounts for most first-week frustration, so this stage puts it front
and centre.
Ready?
Step-by-step lessons
Ask, Convert, Answer
Four short lessons: how input() works, the one trap everybody falls into, asking more than one question, and printing something a person can actually read.
1
input(): Stop and Wait for an Answer
input() does three things: it prints whatever you pass it,
pauses the program, and hands back the line the person typed once they
press Enter.
name = input("Your name: ")
print(f"Welcome, {name}.")
Note the space at the end of "Your name: ". Without it the
cursor sits flush against the colon and the program looks broken. It is a
one-character detail that separates a program that feels finished from one
that does not.
1
Prompt
Say what you want, in the words the person would use.
2
Wait
Nothing after this line runs until Enter is pressed.
3
Return
You get the typed line back, without the Enter.
How this works in the Lab
The exercises here supply the answers for you — you can see exactly what
gets typed above each editor, one line per input() call. Ask
for more answers than are supplied and you get a clear
EOFError rather than a program that hangs forever waiting
for a keyboard that is not there.
Quick check
What happens to the line print("Done") written after an input() call?
2
The Trap: Every Answer Arrives as Text
input()always returns a str.
Someone types 7 and your program receives the text
"7". There is no exception to this and no setting that
changes it.
age = input("Age: ") # they type 30
age + 1 # TypeError: can only concatenate str (not "int") to str
age * 2 # "3030" — worse, because it does not even fail
That second line is the dangerous one. It does not crash, it just silently
produces nonsense, and you find out much later when a total looks
impossible.
The fix is one function call, and the convention is to do it on the same
line as the question:
age = int(input("Age: "))
price = float(input("Price: "))
Fragile
Convert where it is needed
Twelve lines later, and again in three other places. Miss one and the bug is silent.
Sturdy
Convert at the edge
Right where the value enters. Everything downstream works with a real number.
Quick check
A program does quantity = input("How many? ") and then print(quantity * 3). The person types 5. What appears?
3
More Than One Question
Each input() reads exactly one line. Ask three times and you
get three answers, in the order you asked. There is nothing more to it
than that — but the order matters, and it is a common source of confusion
when the answers are being supplied rather than typed.
name = input("Name: ")
item = input("Item: ")
quantity = int(input("How many? "))
print(f"{quantity} x {item} for {name}")
Each answer gets converted to whatever it needs to be. Text stays text; a
count becomes an int; a price becomes a float.
What happens when they type nonsense
int(input("Age: ")) raises a ValueError if
someone types "thirty" — the program stops with a traceback. For now
that is fine and honest. Once you have if statements and
try blocks, in World 2 and World 3, you will be able to
catch it and ask again politely.
Read it. Convert it. Then use it. In that order, every time.
Quick check
A program asks for an item, then a quantity. The answers supplied are Tea then 3. The author swaps the two input() lines but nothing else. What happens?
4
Output People Can Actually Read
print() takes two settings beyond the values themselves.
sep is what goes between them, a space by default.
end is what goes after them, a newline by default.
print("a", "b", sep="-") # a-b
print("2026", "09", "01", sep="/") # 2026/09/01
print("Loading", end="") # next print continues on the same line
For anything tabular, the trick is fixed widths. Strings
have ljust and rjust, which pad a value out to a
given number of characters:
Names padded on the right, numbers padded on the left, and suddenly a
receipt reads like a receipt. The format spec >6.2f is
doing both jobs at once: right-align inside six characters, with two
decimal places.
Quick check
You want two print() calls to produce one line of output. What do you change?
Type it yourself
Code Lab
Four exercises on asking a person a question and doing something sensible with the answer. Each one types its answers in for you — you can see exactly what they are above each editor. Your prompts show up in the console but are not part of what gets checked, so word them however you like.
0 of 4 cleared
Real Python runs right here in your browser — nothing to install, nothing
sent to a server. The interpreter downloads once the first time you press
Run, then stays cached.
01
Ask a question
To do
input() stops the program, waits for someone to type a line,
and hands back what they typed. Whatever you pass to it is printed first
as the prompt.
name = input("What is your name? ")
Notice the space at the end of the prompt. Without it the cursor sits
flush against the question mark, which looks broken.
Your task: ask Your name: , store the answer
in name, and greet them with an f-string reading
Welcome to the dojo, Kenji. — including the full stop.
The answer is typed in for you, so the program can run without you sitting
at the keyboard.
Typed in for you when this runs:Kenji
your_code.py
PythonCtrl↵ to run
Hint
f"Welcome to the dojo, {name}." puts the answer into the sentence. The full stop goes inside the quotes, after the closing brace.
Output
02
Every answer arrives as text
To do
This is the single most common beginner trap, so it is worth stating
plainly: input()always hands back a
str. Type 7 and you get the text
"7", not the number.
age = input("Age: ") age + 1 → TypeError int(age) + 1 → works
So the pattern is: read it, convert it, then use it. Doing the conversion
on the same line is fine and very common:
age = int(input("Age: ")).
Your task: ask How many stages? , convert the
answer to a whole number in stages, and print the XP that
earns at 200 per stage. With 4 typed in, the output is
800 XP.
Typed in for you when this runs:4
your_code.py
PythonCtrl↵ to run
Hint
stages = int(input("How many stages? ")) does the reading and converting in one line. Then f"{stages * 200} XP".
Output
03
More than one question
To do
Each input() reads one line. Ask twice and you get two
answers, in the order you asked for them.
Convert each one to whatever it needs to be — text stays text, a quantity
becomes an int, a price becomes a float.
Your task: ask for an item name, then a quantity, then a
unit price, in that order. Print one line using an f-string:
3 x Tea = 7.50, with the total shown to two decimal places.
Typed in for you when this runs:Tea ⏎ 3 ⏎ 2.5
your_code.py
PythonCtrl↵ to run
Hint
int() for the quantity, float() for the price. Then f"{quantity} x {item} = {quantity * price:.2f}" — the format spec goes after the whole calculation.
Output
04
Output people can actually read
To do
print() has two extra settings that save a lot of fiddling.
sep changes what goes between the values (a space by
default), and end changes what goes after them (a newline by
default).
print("a", "b", sep="-") → a-b print("Loading", end="") → no line break after it
For lining columns up, strings have ljust and
rjust, which pad a value out to a given width.
Your task: print a two-row receipt where the item name is
padded to 10 characters and the price is right-aligned in 6, so the
output is exactly:
Tea............ 2.50 Rice...........12.00
(The dots above stand in for spaces so you can see the widths — print real
spaces.)
your_code.py
PythonCtrl↵ to run
Hint
f"{first_item.ljust(10)}{first_price:>6.2f}" does both jobs at once: ljust pads the name out on the right, and >6.2f right-aligns the number inside six characters with two decimals.
Output
Boss round
Assignment: The Order Desk
One graded task. Pass every check and the stage is cleared and the title is yours — one more stage towards the Python Practitioner certificate.
This one is graded. You can see 2
of the checks up front, and 3
stay hidden until you run. The hidden ones test the same job from angles
you have not been shown, so code that genuinely solves the problem clears
this and code shaped around the visible examples does not.
Pass them all and the stage is yours.
Run the order desk
To do
Someone walks up to the counter. Ask them three questions, work out what
they owe, and print a receipt.
Ask, in this exact order:
the customer's name — keep it as text in name
the item — text, in item
how many — a whole number, in quantity
Every item costs 4.25. Put that in unit_price and
work out total from it.
Then print exactly three lines:
Customer: Kenji Order: 3 x Green Tea Total: 12.75
The total must show two decimal places, and must be calculated. The hidden
checks confirm it holds for a different order as well.
Typed in for you when this runs:Kenji ⏎ Green Tea ⏎ 3
your_code.py
PythonCtrl↵ to run
Hint
Read all three first, converting the quantity with int(). Then total = quantity * unit_price, and print with f-strings — the last one needs {total:.2f} so 12.75 does not come out as 12.749999.
Output
Lock it in
Guess the Term
Read the clues and name the concept. The fewer clues you need, the more points you score.
Round 1Score 0
Keep it handy
Input & Output Quick Reference
The whole stage on one screen.
Reading
input("Name: ")
Prompt, wait, return the typed line. End the prompt with a space.