038. Print() Function
Write to standard output
038. Print() Function
RAM Manager: Terminal Output
Aryan wants his RAM manager to print clean, readable output in the terminal — like htop but simpler. He needs:
- Debug lines prefixed with
DEBUG label:for development logging - Table rows with
|separators between columns - A progress indicator that updates on the same line (no newlines)
DEBUG mem_used: 5432 8192
chrome | 812 | 544MB
Loading [████░░░░]Python’s print() is a function (unlike C’s printf) with keyword arguments: sep= changes the separator between values (default space), and end= changes what’s appended at the end (default newline).
Three bugs in the broken code — each function is wrong for a different reason.
💡 Fun fact: In Python 2, print was a statement (print "hello"), not a function. Converting it to a function in Python 3 was one of the most controversial changes in the language’s history — but it unlocked the ability to redirect output with file= and suppress newlines with end="", making real-world logging and progress-bar code far cleaner.
⚠️ Watch out: print(item) inside a loop prints each item on its own line because end="\n" is the default. Beginners building progress indicators are surprised when their “Loading…” updates appear as a vertical list instead of overwriting on one line. Use print(item, end="") or print(item, end="\r") to stay on the same line.
🤔 Think about it: print(*my_list, sep=", ") and print(", ".join(str(x) for x in my_list)) produce identical output. Which approach would you use in production code — and are there cases where one clearly beats the other?
Learning objectives
- Use print() with multiple arguments
- Customize sep= and end= parameters
- Use *list to unpack a list into print() arguments
Key concepts
- print()
- sep
- end
- stdout
Try it
Concept detail
print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False)
sep: string inserted BETWEEN objects (default: single space) print(“a”, “b”, “c”) → “a b c\n” print(“a”, “b”, “c”, sep=“,”) → “a,b,c\n” print(“a”, “b”, “c”, sep=“”) → “abc\n”
end: string appended AFTER all objects (default: newline) print(“Loading”, end=“”) → “Loading” (no newline, cursor stays on same line) print(“a”); print(“b”) → two lines print(“a”, end=“ “); print(“b”) → “a b” on one line
*args unpacking: print(*my_list) is equivalent to print(my_list[0], my_list[1], …) This lets you use sep= on list elements without joining manually.
file=: redirect output to a file or StringIO (useful for testing and logging) import sys print(“Error!”, file=sys.stderr) → writes to stderr not stdout
flush=True: forces the output buffer to flush immediately — useful when printing progress indicators that should appear before the next line.
Solution
def debug_print(label, *values):
print("DEBUG", label + ":", *values)
def print_table_row(cells):
print(*cells, sep=" | ")
def print_same_line(items):
print(*items, end="")Tests
def test_debug_print():
buf = io.StringIO()
saved = sys.stdout
sys.stdout = buf
debug_print("score", 42, 100)
sys.stdout = saved
assert buf.getvalue().strip() == "DEBUG score: 42 100"
def test_debug_print_colon():
buf = io.StringIO()
saved = sys.stdout
sys.stdout = buf
debug_print("mem", 512)
sys.stdout = saved
output = buf.getvalue().strip()
assert "mem:" in output, f"Expected 'mem:' in output, got: {repr(output)}"
def test_table_row():
buf = io.StringIO()
saved = sys.stdout
sys.stdout = buf
print_table_row(["Alice", "30", "Engineer"])
sys.stdout = saved
assert buf.getvalue().strip() == "Alice | 30 | Engineer"
def test_same_line():
buf = io.StringIO()
saved = sys.stdout
sys.stdout = buf
print_same_line([1, 2, 3])
sys.stdout = saved
output = buf.getvalue()
assert output == "1 2 3" # no trailing newline, space-separated