← Home

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:

  1. Debug lines prefixed with DEBUG label: for development logging
  2. Table rows with | separators between columns
  3. 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

Resources