print() vs repr() — Why Python Has Two Ways to Show a Value

The core idea

Think of print() as "display mode" and repr() as "debug mode."

A simple example first

python

name = "Mahmudul"
print(name)   # Mahmudul
repr(name)    # 'Mahmudul'

Barely a difference here — just quotes. So why does this matter?

Where it actually matters: invisible characters

Strings can contain characters you can't see: spaces, tabs, newlines. print() renders them as actions (a newline moves the cursor down), not as visible marks. repr() shows you the character itself.

python

secret = "hello123 "     # notice the trailing space
print(secret)             # hello123        <- looks totally normal
print(repr(secret))       # 'hello123 '      <- now you can SEE the space

python

message = "line1\nline2"
print(message)
# line1
# line2                   <- newline just moved to a new line, invisibly

print(repr(message))
# 'line1\nline2'          <- newline is shown explicitly as \n

This is the whole lesson in one sentence: print() hides the exact structure of a string; repr() reveals it.

Real use case: debugging a "why doesn't this match?" bug

Imagine you're comparing two values that should be identical — like a password, API key, or secret token stored in two different places (a .env file and a database setting).

python

expected_secret = "abc123"
received_secret = "abc123 "   # someone accidentally left a trailing space when copying it

if received_secret == expected_secret:
    print("Match!")
else:
    print("No match!")   # this runs — but WHY?

Using print() to inspect both values won't help:

python

print(expected_secret)   # abc123
print(received_secret)   # abc123     <- looks IDENTICAL to a human

They look the same. You'd waste time assuming the values are fine and the bug is somewhere else. Now check with repr():

python

print(repr(expected_secret))   # 'abc123'
print(repr(received_secret))   # 'abc123 '

Now the trailing space is visible immediately — mystery solved in one line.

The rule of thumb

SituationUseShowing output to a userprint()Debugging why two "identical-looking" values don't matchrepr()Logging a value where hidden characters might matterrepr()Quick sanity check in a Django/Python shellrepr()

Try it yourself

python

a = "test"
b = "test\t"    # tab character at the end

print(a == b)         # False — but why?
print(a, "|", b)      # try to spot the difference (you probably can't)
print(repr(a), "|", repr(b))   # now you can

One-line takeaway: if two things "look the same" but code says they're not equal, reach for repr() before you doubt anything else.