Python Output
Every Python program needs a way to communicate with the outside world, and the simplest way to do that is to display text on the screen. In Python, this is done with the built-in print() function. Whether you are debugging a script, showing a result to a user, or logging progress in a long-running program, print() is almost always the first tool you reach for. This lesson covers everything about producing output in Python: how print() works internally, its parameters, common formatting techniques, and the mistakes beginners frequently make.
Overview: How Output Works in Python
print() is a built-in function, meaning it is always available without importing anything. When you call it, Python does the following: it takes every argument you pass in, converts each one to a string (by internally calling str() on it), joins those strings together with a separator, appends an ending string, and writes the final result to the standard output stream (usually your terminal or console).
This matters because print() can accept objects of any type — integers, floats, lists, dictionaries, custom objects — and it will automatically convert them to a readable string representation for you. You never need to manually convert a number to text before printing it.
It is also important to understand that print() always returns None. Its job is to produce a side effect (writing text to the screen), not to produce a value your program can use. This trips up many beginners, and we will look at exactly why later in the lesson.
Syntax
The full signature of the print() function is:
print(*objects, sep=' ', end='
', file=sys.stdout, flush=False)
| Parameter | Default | Meaning |
|---|---|---|
*objects |
— | Any number of values to print, separated by commas. Each is converted to a string. |
sep |
' ' (single space) |
The string placed between each object. |
end |
' (newline) |
The string appended after the last object, ending the line by default. |
file |
sys.stdout |
The stream to write to. Rarely changed, but can target sys.stderr or an open file. |
flush |
False |
Whether to force the output buffer to be written immediately instead of waiting. |
The *objects parameter means print() can take zero, one, or many positional arguments: print() alone just prints a blank line, while print(a, b, c) prints all three values separated by sep.
Examples
Example 1: Printing multiple values with a custom separator
name = "Ava"
age = 29
print("Name:", name, "Age:", age)
print("Name", name, "Age", age, sep=" | ")
Output:
Name: Ava Age: 29
Name | Ava | Age | 29
In the first call, four arguments are joined with the default single-space separator. In the second call, sep=" | " replaces that default, so every argument — including the label strings — is joined with " | " instead of a plain space.
Example 2: Controlling line endings with end
total = 0
for n in range(1, 6):
total += n
print(n, end=" ")
print()
print("Sum:", total)
Output:
1 2 3 4 5
Sum: 15
By default, every print() call ends with a newline, so each call starts a fresh line. Here, end=" " replaces the newline with a space, so all five numbers appear on one line instead of five separate lines. The bare print() after the loop supplies the missing newline so that "Sum: 15" starts on its own line.
Example 3: Formatting output with f-strings
quantity = 3
total = 59.997
print(f"{'Item':<10}{'Qty':>5}{'Total':>10}")
print(f"{'Widget':<10}{quantity:>5}{total:>10.2f}")
Output:
Item Qty Total
Widget 3 60.00
F-strings let you embed format specifications directly inside {}. The <10 means “left-align, pad to a width of 10 characters”, >5 means “right-align, pad to width 5”, and >10.2f means “right-align a floating-point number, padded to width 10, with exactly two decimal places”. This is how you build clean, column-aligned output like tables and reports without manually counting spaces.
Under the Hood
When Python executes a line like print("Score:", 42), the following happens step by step:
- Python evaluates each argument, producing the string
"Score:"and the integer42. - For every argument that is not already a string, Python calls
str()on it. So42becomes"42". (Custom classes can control this by defining a__str__method.) - Python joins the resulting strings together using the
sepvalue, producing"Score: 42". - Python appends the
endvalue (a newline, by default) to the joined string. - The final text is written to the stream given by
file, which defaults tosys.stdout, the standard output stream connected to your terminal. - Depending on buffering settings, the text may sit in an internal buffer briefly before actually appearing on screen; passing
flush=Trueforces it out immediately, which is occasionally useful in progress bars or when output is piped to another program. - Finally, the
print()call itself evaluates toNone, since its purpose is the side effect of writing text, not producing a reusable value.
Common Mistakes
Mistake 1: Assuming no separator is added
Beginners often write print("ID", "-", 1023) expecting ID-1023, but forget that the default sep is a single space, so extra spaces sneak in around the dash. The fix is to either pass an empty separator or build the string with an f-string:
print("ID", "-", 1023)
print("ID", "-", 1023, sep="")
print(f"ID-{1023}")
Output:
ID - 1023
ID-1023
ID-1023
The first line shows the default behavior with unwanted spaces. The second and third lines both produce the intended, tightly-joined result.
Mistake 2: Trying to use the return value of print()
Because print() always returns None, storing its result and using it later is a bug, not a way to “capture” what was printed:
def show_message(msg):
result = print(msg)
return result
value = show_message("Saving file...")
print(value)
Output:
Saving file...
None
show_message() prints the message as a side effect, but the value it returns is always None, because that is what print() itself returns. If you actually need the text for later use, build the string first (for example with an f-string) and return that string instead of returning the result of print().
A related pitfall worth knowing about even without a runnable example: writing print("Score: " + 42) raises a TypeError, because + requires both operands to be strings, and Python will not automatically convert the integer for you inside a + expression. Using a comma (print("Score:", 42)) or an f-string (print(f"Score: {42}")) avoids the error entirely, since both of those approaches let print() or the f-string handle the conversion to text.
Best Practices
- Prefer commas or f-strings over
+concatenation when mixing strings with numbers or other non-string values — it avoidsTypeErrorand is easier to read. - Use f-strings (
f"...") for anything beyond the simplest output; they are the most readable and performant way to format values in modern Python. - Use format specifiers like
:.2ffor money and measurements so you control precision instead of relying on however many decimal digits a float happens to have. - Reserve
sepandendfor genuine formatting needs (progress indicators, custom delimiters); don’t rely on the default separator producing exactly the string you want without checking. - Remove or replace debugging
print()calls with proper logging (theloggingmodule) before shipping production code — stray prints clutter output and can’t be turned off selectively. - Don’t try to use the return value of
print(); if you need the formatted text itself, build it with an f-string orstr.format()and print that variable.
Practice Exercises
- Exercise 1: Write a program that stores a product name, price, and quantity in variables, then prints a single line in the exact format
Widget x3 = $59.97using an f-string and a:.2fformat specifier. - Exercise 2: Using a
forloop andprint(..., end=""), print the numbers 1 through 10 on a single line separated by commas, with no trailing comma after the final number. (Hint: build a list of strings and use", ".join(...)in a singleprint()call instead of trying to suppress the last comma inside the loop.) - Exercise 3: Print a small two-column table of three fruits and their prices, right-aligning the prices in a column of width 8 using format specifiers, similar to the table shown in Example 3.
Summary
print()is a built-in function that converts its arguments to strings, joins them withsep(default a space), appendsend(default a newline), and writes the result to standard output.print()always returnsNone; never rely on its return value.- Customize
sepandendto control spacing between values and whether output continues on the same line. - F-strings with format specifiers (like
:.2f,:<10,:>10) are the cleanest way to control decimal precision and column alignment in output. - Mixing strings and numbers with
+raises aTypeError; use commas inprint()or f-strings instead. - Use
logginginstead of strayprint()calls once code moves beyond quick debugging.
