Visual walkthrough — Input with `input()` — always returns string, conversion needed
Parent note: Input with input().
Step 1 — What a keystroke actually is
WHAT. You press the key marked 5. In your head this is "the number five". But a keyboard has no idea about numbers — it only knows keys. Each key sends one tiny label called a character.
WHY. Before we talk about strings, we must earn the word "character". A character is the smallest piece of text: a single symbol like 5, c, !, or even a space. This is the atom everything else is built from.
PICTURE. Look at the figure: the finger presses a key, and what travels down the wire is not a quantity — it is a little tile stamped with the shape '5'.

Step 2 — Many characters make a string
WHAT. You rarely type one key. You type 4, then 2, then Enter. Python lines those character-tiles up in order and calls the whole row a string.
WHY. We need one word for "a row of characters". That word is string (Python type str). A string keeps the characters in order and remembers there are two of them — but it still does not know they mean "forty-two".
PICTURE. Two tiles '4' and '2' snap together into one box labelled "42". The box is a str. Notice the quotes — they are Python's way of saying "this is text, treat it as tiles, not as a quantity".

Step 3 — input() is a catcher that always hands you a string
WHAT. When you call input(prompt), three things happen: it (1) prints the prompt, (2) pauses and waits for you to type + press Enter, (3) hands back the row of tiles you typed — as a str.
WHY. Why a string and never a number? Because at the moment you press keys, Python only has characters. It cannot read your mind. Maybe 5 is a quantity; maybe it is the first digit of a password. To stay safe, Python gives you the raw tiles and lets you decide their meaning.
PICTURE. The input() box is a catcher's mitt. Keystrokes fly in; a single str value drops out the bottom, no matter what you typed.

x = input("Enter a number: ") # you type 5
print(type(x)) # <class 'str'> ← a string, not the number 5Step 4 — Why "3" + "4" refuses to be 7
WHAT. You read two inputs, "3" and "4", and write +. You expect 7. You get "34".
WHY. The + symbol is overloaded — its job depends on the types beside it. For numbers, + means add. For strings, + means concatenate (glue the tile-rows end to end). Since both values are strings, Python glues: "3" then "4" → "34".
PICTURE. On the left, two number-blocks merge heights into 7. On the right, two tile-rows slide together into "34". Same +, two completely different actions — decided purely by type.

See String Concatenation vs Arithmetic and Operators in Python for the overloading in depth.
Step 5 — int() translates a number-string into a real number
WHAT. To make math work you wrap the string in int(). int("42") reads the tiles '4','2', understands them as digits, and builds the actual number 42.
WHY. We use int() (and not, say, float()) precisely when the value is a whole count — an age, a quantity, a repeat-count. It is the tool whose one job is "turn a digit-string into a whole number". After conversion, + sees numbers, so it adds.
PICTURE. The tile-box "42" goes into the int() translator and comes out as a solid number-block 42. The quotes vanish — that is the visible sign it stopped being text.

a = int(input("First number: ")) # "3" → 3
b = int(input("Second number: ")) # "4" → 4
print(a + b) # 7 ✅For decimals use float(...) instead — see Type Conversion (Casting) and Variables and Data Types.
Step 6 — The degenerate case: when int() cannot translate
WHAT. int() only works on strings that look like whole numbers. Give it "twenty" or "3.5" and it stops with a ValueError.
WHY. A translator that guesses would be dangerous. "twenty" has no digits; "3.5" has a dot int() was not built to read. So Python refuses loudly rather than inventing an answer. This is a feature: it points at the exact bad input.
PICTURE. Three tile-boxes enter the translator. "42" passes (green). "3.5" bounces (needs float()). "twenty" bounces (all letters). Each rejected box shows the ValueError stamp.

x = int(input("Age: ")) # user types twenty
# ValueError: invalid literal for int() with base 10: 'twenty'Real programs wrap this in a guard — see Exceptions and try-except.
Step 7 — The empty and space edge cases
WHAT. Two sneaky inputs: pressing Enter with nothing typed, and typing spaces around a number.
WHY. You must never meet a scenario you have not seen:
- Empty input →
input()returns""(the empty string — a box with zero tiles).int("")→ValueError. - Spaces →
int(" 42 ")actually succeeds →42, becauseint()politely trims surrounding whitespace. Butint("4 2")(a space inside) fails — the gap breaks the digit run.
PICTURE. Left box: an empty outline "" feeding the translator and bouncing. Middle: " 42 " with the outer spaces greyed out, passing to 42. Right: "4 2" with an inner gap, bouncing.

int("") # ValueError — nothing to read
int(" 42 ") # 42 ✅ outer spaces trimmed
int("4 2") # ValueError — inner gap breaks the numberThe one-picture summary
Everything at once: keystrokes → catcher → string → two roads. Road A (+ on strings) glues to "34" (a bug). Road B (wrap in int()/float()) gives a real number, so + adds to 7.

Recall Feynman retelling — explain the whole walk to a 12-year-old
You press keys. Each key drops a little tile with a shape drawn on it, like '5'. Python lines the tiles into a row and calls it a string — but it's still just drawings, not real numbers. The input() mitt always catches a row of drawings, never a number, because at that moment there are only tiles to catch. Now if you glue two drawing-rows with +, you just tape the papers together: "3" and "4" become "34" — nonsense as maths. To do real maths you must first read each drawing and rebuild the real number in your head; that "reading" is what int() does. It works when the drawing is clearly a whole number ("42"), and it politely ignores spaces around the edges. But if the paper says "twenty", or has a dot like "3.5", or is blank, int() throws up its hands and says ValueError — I can't read this as a whole number. That refusal is a gift: it tells you exactly which paper was unreadable.
Connections
- Variables and Data Types —
str,int,floatare the tiles-vs-numbers idea made formal. - Type Conversion (Casting) —
int(),float(),str()in depth. - String Concatenation vs Arithmetic — why
+splits into two behaviours. - print() Function — showing your converted results.
- Exceptions and try-except — catching the
ValueErrorfrom Step 6. - Operators in Python — operator meaning depends on operand type.