When a Python script runs and produces no output, there is no way to know if it worked. print() is how a program speaks. This tutorial covers how to produce output in Python from your very first print() call through f-strings, separators, and line endings — building not just syntax knowledge, but a mental model of what the interpreter is actually doing at each step.
Producing output is how a program communicates. Without it, a script can run perfectly but leave no trace. Python makes this straightforward through the built-in print() function, which works from the first line you ever write and scales to cover formatted multi-line reports. This tutorial walks through every piece of that function so you understand not just what to type, but why each part works the way it does.
Key Concepts Glossary
These terms appear throughout the tutorial. Having names for these ideas gives you language to think with — and to search with when you encounter them again in documentation or error messages.
stdoutStandard Stream- The default destination for
print()output. "Standard output" is one of three streams every process has (the others arestdinfor input andstderrfor errors). When you see output in your terminal, it came throughstdout. Understanding this name helps when you read error messages or redirect output in shell scripts. - Keyword Arguments Function Concept
- Arguments passed to a function by name rather than position.
sepandendinprint()are keyword arguments — you writesep="-", not just"-". This pattern appears in every Python function that has optional parameters. Recognizing it here lets you read any function signature with confidence. - Type Coercion vs. Explicit Conversion Type System
- Some languages silently convert values between types (coercion). Python does not — it requires you to convert explicitly using functions like
str(). This is whyprint()can accept integers directly (it converts internally) but the+operator cannot join a string and an integer (it has no conversion rule for mismatched types). - String Interpolation Formatting
- The general term for embedding variable values inside a string. f-strings are Python's string interpolation feature. Other languages have equivalents: template literals in JavaScript, string interpolation in Ruby. Knowing the general term helps you search documentation and map the concept across languages.
- Built-in Function Python Internals
- A function that is always available in Python without importing anything.
print(),str(),len(), andinput()are all built-ins. They live in a special module calledbuiltinsthat Python loads automatically. When Python can't find a name, it checks this module last before raising aNameError. - Escape Sequence String Syntax
- A two-character combination starting with a backslash that represents a character that cannot easily be typed directly in a string literal.
\nis a single newline character;\tis a single tab. The backslash "escapes" the normal meaning of the character that follows it. The same mechanism appears in file paths, regular expressions, and network protocols.
The print() Function
The print() function is built into Python, meaning you never need to import anything to use it. You call it by typing its name followed by parentheses, and you place whatever you want to display inside those parentheses. Python's official documentation describes print() as sending its arguments to the standard output stream, which in practice means your terminal window.
The complete signature of print(), as documented by the Python Software Foundation, is:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
Every parameter except *objects has a default. That is why print("hello") works — you are relying on every default at once. The parameters you will use at this stage are sep (the separator between values), end (what to print at the end of the call), file (where to send output — defaults to the terminal), and flush (whether to force the output buffer to empty immediately — added in Python 3.3, defaults to False). Each is covered in context through this tutorial.
When Python runs print("Hello, world!"), it looks up print in the builtins module, calls it as a function, and internally calls sys.stdout.write() to send the text to the terminal. The newline you see at the end is added by print() itself — it's the end="\n" default. This is why print() and sys.stdout.write() are equivalent, except that sys.stdout.write() adds no newline and returns a character count instead of None.
print("Hello, world!")
Running that single line produces:
Hello, world!
String literals inside print() can use single quotes ' or double quotes ". Both produce identical results. Choose whichever you prefer and stay consistent within a project.
Printing Numbers and Empty Lines
You can pass integers and floats directly to print() without wrapping them in quotes. Python converts numeric values to their string representations automatically. Calling print() with nothing inside produces a blank line, which is useful for spacing output.
print(42)
print(3.14)
print()
print("After a blank line")
42
3.14
After a blank line
Readable output is important for debugging. Insert blank lines between sections of printed data while developing to quickly spot where different parts of your program start and stop.
print() is a function call — the same syntactic pattern you will use for every function in Python, built-in or custom. The parentheses, the arguments inside them, and the way Python evaluates them left to right are all universal. What you learn here about calling print() applies directly to calling any other function.
Build a valid Python statement that prints the text Hello, Python! to the screen:
print, not input or display — those are either a different function or not a Python built-in. Arguments go inside parentheses (), not square brackets []. The string must be in quotes inside the parentheses.
Printing Variables and Multiple Values
Programs rarely print fixed text only. Usually you need to display the result of a calculation or the current value of a variable. You pass a variable to print() the same way you pass a string — just use the variable name without quotes.
name = "Alex"
age = 29
print(name)
print(age)
Alex
29
The sep Parameter
Pass multiple values to print() by separating them with commas. Python places a single space between each value by default. The sep parameter lets you replace that space with any string you choose, including an empty string to remove spacing entirely.
# Default sep is a single space
print("Python", "is", "fun")
# Custom sep
print("2026", "04", "03", sep="-")
# No spacing between values
print("http", "//", "example.com", sep="")
Python is fun
2026-04-03
http//example.com
The end Parameter
By default, print() adds a newline character at the end of every call, so the next call starts on a fresh line. The end parameter replaces that newline with any string you specify. Setting end="" keeps all output on the same line.
# Default end (newline after each call)
print("Line one")
print("Line two")
# Same line using end=""
print("Loading", end="")
print("...", end="")
print(" done")
Line one
Line two
Loading... done
- Default value
- A single space character
" " - Common use
- Formatting dates, paths, or lists where you need a specific delimiter between multiple printed values in a single call.
- Default value
- A newline character
"\n" - Common use
- Building progress indicators, same-line updates, or suppressing the automatic newline when constructing output piece by piece across multiple calls.
- Example
print("a", "b", "c", sep="|", end="!\n")producesa|b|c!followed by a newline.- Why it matters
- Both parameters are keyword arguments and can appear in any order, but both control entirely separate parts of the output: one governs spacing between items, the other governs what the entire call ends with.
What does the following code print? Run it in your head before selecting an answer.
print("A", "B", "C", sep="|", end="!\n")
print("done")
sep="|" places a pipe between each value, producing A|B|C. end="!\n" replaces the default newline with ! followed by an explicit newline — so the first line ends with !. The second print("done") starts fresh on a new line with its own default end="\n".
The code below is supposed to print "2026-04-03" but something is wrong. Click the line you think contains the bug, then hit check.
sep=" " to sep="-". The goal is to join the three date parts with a hyphen, but a space was used instead, producing 2026 04 03 rather than 2026-04-03.
Escape Sequences and Multi-Line Output
String literals in Python support escape sequences — special two-character combinations that start with a backslash and represent characters that would otherwise be difficult or impossible to type directly inside a string. Beginners encounter them constantly because print() uses them internally for its own defaults.
The two you will see most often are \n (newline) and \t (tab). They can appear anywhere inside a string passed to print().
# \n inserts a newline inside a string
print("Line one\nLine two\nLine three")
# \t inserts a tab stop
print("Name:\tJordan")
print("Score:\t98")
Line one
Line two
Line three
Name: Jordan
Score: 98
When end="\n" is the default for print(), that \n is the same newline escape sequence. Understanding escape sequences explains why changing end controls line breaks.
Triple-Quoted Strings for Multi-Line Output
When you need to print a long block of text across multiple lines, embedding \n throughout a single string quickly becomes hard to read. Triple quotes — either """ or ''' — let you write the text exactly as it should appear, with real line breaks inside the string itself.
print("""Name: Jordan
Score: 98
Grade: A""")
Name: Jordan
Score: 98
Grade: A
Triple-quoted strings preserve every whitespace character exactly as written, including leading spaces on each line. Watch your indentation — any spaces before the text inside the triple quotes will appear in the output.
The same \n you see here appears throughout Python — in file reading, network responses, and log output. It is not a print()-specific idea. When you later read a file with open() and strip newlines from each line, you are dealing with the same character. Escape sequences are a universal string concept, not a beginner-mode shortcut.
Other String Formatting Methods
f-strings are the recommended approach for new Python code, but you will encounter two older formatting methods when reading existing code or third-party libraries. Knowing how they work prevents confusion when you see them in the wild.
str.format()
The str.format() method, introduced in Python 2.6 via PEP 3101, works by placing empty curly braces {} as placeholders inside a string, then passing the values to fill them in as arguments to .format(). Positional and named placeholders are both supported.
name = "Jordan"
score = 98
# Positional placeholders — filled in order
print("Name: {}, Score: {}".format(name, score))
# Named placeholders — order does not matter
print("Score: {s}, Name: {n}".format(n=name, s=score))
# Format spec works the same way as in f-strings
price = 49.99
print("Total: ${:.2f}".format(price))
Name: Jordan, Score: 98
Score: 98, Name: Jordan
Total: $49.99
The % Operator (Legacy)
Python's original string formatting method uses the % operator, inherited from C's printf and available since Python 1. You write format codes like %s (string) and %d (integer) inside a string, then provide the values after the % operator. You will encounter it in older code and tutorials.
name = "Jordan"
score = 98
# % formatting — two formats codes, two values in a tuple
print("Name: %s, Score: %d" % (name, score))
# Float with two decimal places
price = 49.99
print("Total: $%.2f" % price)
Name: Jordan, Score: 98
Total: $49.99
The % operator has been in Python since version 1. str.format() was introduced in Python 2.6 (PEP 3101) to address its limitations — primarily that % only supports a fixed set of types and has a well-known bug when formatting a single tuple. f-strings arrived in Python 3.6 (PEP 498) as the cleanest and fastest option. For new code written on Python 3.6+, f-strings are the correct default. The older methods remain because they are present in decades of existing code you will eventually read.
When using the + operator to build output strings, Python requires every value to already be a string. Passing an integer directly raises a TypeError. This is one of the first errors beginners encounter, and understanding why it happens makes it easy to fix.
age = 29
# This raises a TypeError — cannot concatenate str and int
print("Age: " + age)
# Fix 1: wrap the integer with str()
print("Age: " + str(age))
# Fix 2 (preferred): use an f-string instead
print(f"Age: {age}")
TypeError: can only concatenate str (not "int") to str
Age: 29
Age: 29
The TypeError above does not occur with print(age) alone, because print() handles the conversion internally. The error only appears when you try to concatenate a non-string value using + before passing it to print().
The code below should print "Score: 98" but crashes instead. Click the line with the bug, then hit check.
print("Score: " + score) to print("Score: " + str(score)) or use print(f"Score: {score}"). The + operator cannot join a string and an integer directly — Python requires both sides to be the same type.
What does this code print? Think through each line before selecting.
name = "Sam"
score = 42
print(f"Player: {name}, Score: {score * 2}")
{score * 2} evaluates the arithmetic first, producing 84, then inserts the result. The expressions inside {} are fully evaluated before the string is built. This is string interpolation at work: Python replaces placeholders with computed values at runtime.
Concatenating strings and variables with the + operator works but gets cluttered quickly. f-strings, introduced in Python 3.6, give you a cleaner syntax. Prefix a string literal with the letter f and place any variable name or expression inside curly braces. Python evaluates what is inside the braces and inserts the result into the string.
PEP 498, which introduced f-strings to Python 3.6, describes them as providing a concise, readable way to include the value of Python expressions inside strings — a design intent that also yields measurable performance improvements over older formatting methods. (Source: PEP 498, Python Software Foundation)
name = "Jordan"
score = 98
# Using + concatenation (works but messy)
print("Name: " + name + ", Score: " + str(score))
# Using an f-string (clean and readable)
print(f"Name: {name}, Score: {score}")
Name: Jordan, Score: 98
Name: Jordan, Score: 98
Expressions Inside f-Strings
The curly braces in an f-string accept any valid Python expression, not just variable names. You can perform arithmetic, call functions, or use conditional expressions directly inside the braces.
price = 49.99
quantity = 3
print(f"Total: ${price * quantity:.2f}")
print(f"Item count: {quantity}")
print(f"{'In stock' if quantity > 0 else 'Out of stock'}")
Total: $149.97
Item count: 3
In stock
The :.2f inside the f-string curly braces is a format specification. It tells Python to display the number as a float with exactly two decimal places. Format specifications always follow a colon after the expression.
f-string expressions are evaluated eagerly — at the moment the string is created, not later. When Python encounters f"Total: ${price * quantity:.2f}", it evaluates price * quantity immediately, applies the :.2f format, and embeds the result. There is no deferred evaluation. This matters when you use f-strings inside loops: each iteration captures the current value of variables at that moment, not their future values.
Python 3.8 added a debugging shortcut inside f-strings that most tutorials skip entirely. Place an equals sign after any expression inside the braces and Python will print both the expression text and its value:
price = 49.99
quantity = 3
print(f"{price=}")
print(f"{quantity=}")
print(f"{price * quantity=}")
price=49.99
quantity=3
price * quantity=149.97
This works on any valid expression — not just variable names. The output shows the expression as written in your source code alongside the evaluated value. It is the fastest way to inspect variables during development without reaching for a debugger. (Source: Python 3.8 Release Notes, Python Software Foundation)
f-string expressions can hold any valid Python expression — including function calls, list comprehensions, and method calls. You will use this constantly once you reach collections and loops. For now, arithmetic and variable names are the main use case. The pattern of {expression} inside a string is the same one you will encounter in template engines, logging formatters, and web frameworks.
Under the Hood: stdout and the Type System
Two deeper ideas explain nearly every quirk a beginner encounters with print(). Neither requires advanced knowledge — they are simply the "why" behind behaviors the tutorial has already shown.
Why print() Goes to the Terminal
Every process that runs on an operating system is given three standard streams: stdin (standard input, where keyboard input arrives), stdout (standard output, where normal output goes), and stderr (standard error, where error messages go). print() writes to stdout by default. This is why you can redirect output in the shell with python script.py > output.txt — you are redirecting stdout to a file, and print() follows automatically. print() also has a file keyword argument that lets you send output anywhere a file-like object can receive it.
import sys
# Both print the same text — print() uses stdout by default
print("Sent to stdout")
print("Also stdout", file=sys.stdout)
# This sends to stderr instead (used for error/diagnostic messages)
print("This is an error message", file=sys.stderr)
You will see stderr referenced often in Python error tracebacks and logging documentation. Now you know what it refers to: a separate output channel reserved for diagnostic information, kept distinct from normal program output so tools can treat them differently.
Why Python Does Not Coerce Types in Expressions
Python is a strongly typed language. This means it does not silently convert values from one type to another in expressions — you must convert explicitly. When you write "Score: " + 98, Python does not guess that you want 98 as a string. It raises a TypeError instead. This design is intentional: silent type coercion in other languages produces bugs that are very difficult to find because the program continues running with corrupted data. Python's refusal to guess is a feature, not a limitation.
print() appears to contradict this because it accepts integers directly. It does not — internally, print() calls str() on every argument before displaying it. The conversion is explicit, just hidden inside the function. The + operator has no such conversion rule, which is why the two behaviors feel inconsistent to beginners.
Apply what you know about how print() processes its arguments. What does this code print?
print(True, 0, 3.5, sep=" | ")
print() calls str() on each argument internally — True becomes "True", 0 becomes "0", 3.5 becomes "3.5". No TypeError occurs because print() handles the conversion explicitly before joining. The sep " | " is placed between each converted string, producing True | 0 | 3.5. Option D shows the right values but with added quotes that do not appear in terminal output.
Common Problems and How to Solve Them
These are the problems that actually stop beginners — not the obvious syntax errors, but the ones where the code runs without crashing and still produces the wrong result, or where the right behavior requires knowing something that no introductory paragraph tells you.
- Why it happens
- When stdout is connected to an interactive terminal, Python flushes the buffer after every newline — output appears immediately. When you redirect to a file (
python script.py > out.txt), Python switches to full buffering: it holds output in memory and writes it in large chunks. If a script crashes or finishes before the buffer is flushed, some output may never reach the file, and the order of what does appear can look wrong. - The solution
- Pass
flush=Trueto anyprint()call that must reach the destination immediately:print("Step complete", flush=True). Alternatively, run Python with the-uflag (python -u script.py > out.txt), which forces unbuffered stdout for the entire process. The-uapproach is useful in long-running scripts where you want real-time visibility into a redirected log file without modifying everyprint()call.
- Why it happens
- When
print()callsstr()on an argument, Python looks for a__str__method on the object. If none exists, it falls back to__repr__. If neither is defined on the class, Python uses the default inherited fromobject, which produces something like<MyClass object at 0x7f3c...>— a type name and memory address that tells you nothing about the object's state. - The solution
- Define
__str__on your class to control whatprint()displays. Define__repr__to control what appears in the interactive REPL and in debugging contexts. A common pattern is to make__repr__return a string that could reconstruct the object, and__str__return a clean, readable description. If you only define one, define__repr__— when__str__is not defined, Python falls back to__repr__, but the reverse is not true: a missing__repr__does not fall back to__str__. - Example
class Point: def __init__(self, x, y): self.x = x self.y = y def __str__(self): return f"Point({self.x}, {self.y})" p = Point(3, 7) print(p) # Point(3, 7)
- Why it happens
- Python preserves every character inside a triple-quoted string exactly as written, including the leading whitespace that makes the code look tidy inside an indented block. When you print that string, those spaces appear as visual indentation in the output — which is rarely what you intended.
- The solution
- Use
textwrap.dedent()from the standard library. It measures the common leading whitespace across all non-empty lines and strips it uniformly. This lets you keep the visual indentation in source while producing clean output at runtime. Import it once at the top of the file:from textwrap import dedent. The alternative — aligning the triple-quoted string against the left margin of the file — works but creates a visual inconsistency in the source that many style guides discourage. - Example
from textwrap import dedent def show_help(): print(dedent(""" Usage: run the script with a filename Options: --verbose show detailed output --help show this message """).strip())
- Why it happens
- Using
end=""suppresses the newline and keeps output on one line, but stdout may still hold the characters in its internal buffer until it has enough data to write efficiently. The result: a loop printing individual dots finishes the loop first, then flushes everything at once — you see the complete output instantly instead of incrementally. - The solution
- Add
flush=Truealongsideend="". The combination forces each character out of the buffer as it is printed:print(".", end="", flush=True). This is the standard pattern for lightweight terminal progress indicators in Python scripts without importing any external library. Note thatflush=Truehas a performance cost when called in a tight loop — it is appropriate for human-visible feedback, not for high-frequency logging.
- Why it matters
- Beginners are often told "always use f-strings," which is reasonable for display output but is not the right choice in every context. Using the wrong method for the situation produces code that works but is harder to maintain, test, or reuse.
- When to use f-strings
- f-strings are the right default for output where the template and the data are defined in the same place. They are concise, readable, and fast. They are the correct choice for the majority of
print()calls. - When to use str.format()
str.format()is appropriate when the template is defined separately from the values — for example, a message template stored in a configuration file, a database, or a dictionary of translatable strings. f-strings require the variable to be in scope at the point the string is written;str.format()lets you defer that binding. It is also the better choice when you need to reuse the same template with different data across multiple calls.- When to use concatenation
- String concatenation with
+is appropriate in performance-sensitive loops where you are building strings from other strings and all types are already known to bestr. Even then, joining a list with"".join(parts)is faster than repeated+operations because each+creates a new string object in memory.
How to Use print() to Get Output in Python
By this point you have seen every tool individually. Here is how they fit together as a decision sequence — the mental model an experienced Python programmer uses when writing output code, distilled into four questions to ask yourself each time.
-
Call print() with a string
Type
print()and place your text inside the parentheses surrounded by either single or double quotes. Save your file and run it. The text appears immediately in the terminal. This is the foundation of every output operation in Python.What is less obvious at this stage is what is happening at the interpreter level.
print()is not writing characters one at a time. It callssys.stdout.write()internally and flushes the buffer based on whether stdout is attached to an interactive terminal or a pipe. When you run a script normally, stdout is line-buffered — output appears after each newline. When you redirect to a file (python script.py > out.txt), it becomes fully buffered, and you may needflush=Trueto force output through immediately. This distinction does not matter for simple beginner programs, but understanding it prevents confusion when output appears out of order in automated pipelines. -
Print a variable value
Create a variable and pass it to
print()without quotes. Python converts the value to a string representation and displays it. To mix static text and a variable in a single readable call, use an f-string: prefix the opening quote withfand place the variable name inside curly braces.The deeper mechanism is
__str__versus__repr__. Whenprint()converts an object, it calls the object's__str__method — the human-readable representation. If__str__is not defined, Python falls back to__repr__. This distinction matters when you start building your own classes:print(my_object)will display whatever__str__returns. Custom objects that do not define__str__will print something like<MyClass object at 0x7f...>— functional but not helpful. Defining__str__on your classes makesprint()output meaningful from day one. -
Control spacing and line endings
Use the
sepkeyword argument to replace the default space between multiple values. Use theendkeyword argument to replace the default newline that follows each call. Settingend=""lets consecutiveprint()calls build up a single line of output together.A non-obvious use case for
endis progress indicators. In terminal scripts,print(".", end="", flush=True)inside a loop produces a growing row of dots on one line — a lightweight progress display that does not require any external library. Theflush=Trueargument is critical here: without it, buffered stdout may hold the dots until the loop ends, defeating the purpose. The combination ofend=""andflush=Trueis a standard pattern for real-time terminal feedback in Python scripts. Similarly,sepis commonly paired with*iterableunpacking:print(*my_list, sep="\n")prints each element of a list on its own line without writing an explicit loop — a concise idiom you will encounter in production code. -
Handle special characters and multi-line output
Use escape sequences like
\n(newline) and\t(tab) inside string literals to control layout within a singleprint()call. For multi-line blocks of text, triple-quoted strings (""") let you write the output across real lines without embedding\nmanually. When concatenating strings with+, convert any non-string values withstr()first to avoid aTypeError.One problem beginners encounter is indentation bleeding into triple-quoted strings. When the string is indented to match surrounding code, those leading spaces become part of the string content and appear in the output. The standard solution is
textwrap.dedent()from the standard library, which strips common leading whitespace from all lines. Another option is to align the triple-quoted string against the left margin, accepting the visual inconsistency inside the source file. Understanding this trade-off — readable source code versus clean output — is a practical judgment call that comes up every time you write multi-line terminal messages, help text, or log output.For the TypeError, the deeper solution is not just to remember to call
str(). It is to choose the right tool for the job. String concatenation with+is appropriate when you are building strings from other strings in a performance-sensitive loop and already control all types. f-strings are better for display output because they handle conversion internally and keep the intent readable.str.format()is worth knowing for templates that are defined separately from their data — for example, message templates loaded from configuration. Each method has a context where it is the cleaner choice; no single one is always correct.
Python Output Summary Points
print()is a built-in function that sends values tostdout— the standard output stream — which appears as your terminal by default. No import is needed.- String literals passed to
print()must be wrapped in single or double quotes. Variable names are passed without quotes.print()callsstr()internally on every argument, which is why it can display integers and floats without raising aTypeError. - Multiple values separated by commas inside
print()are joined with a space by default.sepis a keyword argument that replaces that space with any string you choose. - Each
print()call appends a newline by default.endis a keyword argument that replaces the newline with any other string, including an empty string. - Escape sequences like
\n(newline) and\t(tab) can appear anywhere inside a string to control layout. They are notprint()-specific — the same sequences appear in file I/O, network output, and log messages. Triple-quoted strings (""") preserve real line breaks without any escape sequences. - f-strings (prefix
fbefore the opening quote) are Python's string interpolation feature. Expressions inside curly braces are evaluated eagerly — at the moment the string is created — and the results are embedded in place. Any valid Python expression works inside the braces. - The
:.2fsyntax after a colon inside f-string braces is a format specification. It controls how the evaluated value is rendered as text (decimal places, padding, alignment). str.format()is an older interpolation method you will encounter in existing code. Curly-brace placeholders are filled in by values passed to.format(). f-strings are preferred for new code — they are more readable and faster, because they are compiled into optimized bytecode at parse time rather than invoking a method call at runtime.- Python is strongly typed: it does not silently convert values in expressions. The
+operator requires both sides to be the same type. Passing an integer without converting it first withstr()raises aTypeError. f-strings andprint()handle this conversion internally. print()has afilekeyword argument that accepts any file-like object. This lets you redirect output tosys.stderrfor error messages, or to an open file handle. The three standard streams —stdin,stdout,stderr— are a universal operating system concept, not Python-specific.
With these tools and the mental model behind them, you can produce any output a beginner program requires. The concepts that appear here — keyword arguments, type conversion, standard streams, string interpolation — are not beginner scaffolding. They are the real mechanisms Python uses at every level of complexity.
Sources and Further Reading
Every technical claim in this tutorial is traceable to official Python documentation or the PEPs that introduced each feature. The sources below are listed in the order topics appear in the article.
-
Python Software Foundation. Built-in Functions — print(). Python 3 Documentation.
docs.python.org/3/library/functions.html#print
— The complete, authoritative signature and parameter descriptions for
print(), includingflush(added in Python 3.3) andfile. - Smith, Eric V. PEP 498 — Literal String Interpolation. Python Software Foundation, 2015. peps.python.org/pep-0498/ — The proposal that introduced f-strings in Python 3.6. Documents design decisions, expression evaluation rules, and comparisons to prior formatting methods including PEP 215.
-
Talin. PEP 3101 — Advanced String Formatting. Python Software Foundation, 2008.
peps.python.org/pep-3101/
— The proposal that introduced
str.format()in Python 2.6. Explains the motivation for replacing%-formatting. -
Python Software Foundation. What's New In Python 3.8 — f-strings: = for quick debugging. Python 3 Documentation.
docs.python.org/3/whatsnew/3.8.html
— Documents the
=specifier added to f-strings in Python 3.8 for inline debugging output. -
Python Software Foundation. textwrap — Text Wrapping and Filling. Python 3 Standard Library Documentation.
docs.python.org/3/library/textwrap.html
— Reference for
textwrap.dedent(), which strips common leading whitespace from triple-quoted strings. -
Python Software Foundation. sys — System-specific parameters and functions. Python 3 Standard Library Documentation.
docs.python.org/3/library/sys.html#sys.stdout
— Documents
sys.stdout,sys.stderr, andsys.stdin, including buffering behavior and the effect of the-uflag.
Frequently Asked Questions
print() is Python's built-in function for producing output. It sends text or data to the terminal by default. You call it by typing print() and passing one or more values inside the parentheses.
Pass multiple values to print() separated by commas. By default, Python inserts a single space between each value. You can change this separator with the sep parameter.
sep controls what character or string is placed between each value passed to print(). The default is a single space. Setting sep='' removes spacing; sep='-' inserts a hyphen between values.
end controls what is printed at the very end of the output. The default is a newline character, which is why each print() call starts on a new line. Setting end='' keeps the cursor on the same line.
An f-string is a formatted string literal introduced in Python 3.6. You prefix a string with f or F and place variable names or expressions inside curly braces {}. Python evaluates the expressions and inserts their values into the string at runtime.
Use an f-string: f'The value is {variable}'. This embeds the variable directly in the string. You can also concatenate with the + operator or use str.format(), though f-strings are the readable option for beginners.
Yes. print() accepts integers, floats, and other data types. Python converts them to their string representations automatically before displaying them.
Set end='' in the print() call. This replaces the default newline with an empty string, so the next print() call continues on the same line.
Escape sequences are two-character combinations starting with a backslash that represent special characters inside a string. The two beginners encounter first are \n, which inserts a newline, and \t, which inserts a tab. They can appear anywhere inside a string passed to print() and control the layout of your output without requiring separate print() calls.
Two approaches work well. You can embed \n newline escape sequences directly inside a regular string: print("Line one\nLine two"). Alternatively, use a triple-quoted string, which preserves real line breaks written directly in your code: print("""Line one\nLine two"""). Triple quotes are easier to read when the output spans several lines.
Both methods embed values into strings, but f-strings (introduced in Python 3.6) are more concise. With str.format(), you write placeholders as {} in the string and pass values as arguments to .format(): "Name: {}".format(name). With an f-string, the variable goes directly inside the braces with no separate call: f"Name: {name}". f-strings are also slightly faster and are the recommended style for new code.
The + operator in Python requires both sides to be the same type. When you write "Score: " + 98, you are trying to join a string and an integer, which Python does not allow. Fix it by converting the number first: "Score: " + str(98). The easier solution is to use an f-string instead — f"Score: {98}" — because f-strings handle the type conversion internally.
stdout stands for standard output — one of three streams every process is given by the operating system. The other two are stdin (standard input) and stderr (standard error). print() writes to stdout by default, which is why output appears in your terminal. You can redirect stdout to a file using the shell: python script.py > output.txt. print() also has a file keyword argument that lets you send output to sys.stderr or any file-like object directly from Python code.
Keyword arguments are arguments passed to a function by name rather than by position. When you write print("a", "b", sep="-"), sep="-" is a keyword argument — Python matches it to the sep parameter by name, not by where it appears in the call. This allows sep and end to have default values that you only need to specify when you want to override them. The same pattern appears throughout Python in virtually every function that has optional parameters, making it one of the most important syntactic patterns to recognize early.
String concatenation builds a new string by joining pieces with the + operator: "Hello, " + name. It requires all pieces to already be strings, which is why non-string values must be converted with str() first. String interpolation embeds expressions directly inside a string template using special syntax — in Python, f-strings: f"Hello, {name}". Interpolation handles type conversion internally, is more readable when mixing text and variables, and evaluates expressions at the point the string is created. f-strings are Python's string interpolation feature; the concept exists in many languages under different names.
Added in Python 3.8, the = specifier inside an f-string prints both the expression text and its evaluated value in a single call. Write f"{variable=}" and Python outputs variable=value — the name as written in your source code, an equals sign, and the result. For example, print(f"{quantity=}") where quantity is 3 prints quantity=3. It works on any valid expression: f"{price * quantity=}" prints price * quantity=149.97. This is the fastest way to inspect a value during development without adding a separate label string or opening a debugger.
The % operator is Python's original string formatting method, inherited from C's printf and present since Python 1. It uses format codes like %s for strings and %d for integers: "Name: %s" % name. You do not need to use it for new code — f-strings are the correct default on Python 3.6 and later. You do need to recognize it when reading older tutorials, open source libraries, and codebases written before Python 3.6. Understanding what it does prevents confusion when you encounter it in the wild.
The % operator has been in Python since the beginning. str.format() was introduced in Python 2.6. f-strings require Python 3.6 or later — they will not work on Python 2 or Python 3.5 and earlier. The = debug specifier inside f-strings requires Python 3.8 or later. The flush parameter in print() was added in Python 3.3. If you are starting fresh today, install Python 3.11 or later and you have access to all features covered in this tutorial.