Dataslope logoDataslope

Strings

Literals, indexing, slicing, methods, and f-strings

A str in Python 3 is an immutable sequence of Unicode code points. Strings are one of the most-used types in the language—text is everywhere—and Python gives you a rich toolkit for working with them.

Every snippet on this page runs in your browser—no setup required.

Real-world context: Text is everywhere

Strings show up in almost every program:

  • Web apps: HTTP headers, JSON payloads, URLs, query parameters, HTML templates.
  • Data pipelines: CSV rows, log lines, file paths, column names.
  • Automation scripts: command output, configuration files, environment variables.
  • Games: dialogue, item names, save files.

Understanding strings—indexing, slicing, formatting, and the immutability gotcha—is essential to productive Python programming.

String literals

There are four ways to write a string literal. They're all equivalent at the value level—pick whichever avoids backslash escapes.

Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2

Escape sequences

SequenceMeaning
\\nnewline
\\ttab
\\\\backslash
\\', \\"quote of that kind
\\u00e9Unicode code point (here, é)
\\xffhex byte
Code Block
Python 3.13.2

Raw strings

Prefix a literal with r to disable escape processing. Useful for regex patterns and Windows paths.

Code Block
Python 3.13.2
Code Block
Python 3.13.2

Indexing and slicing

Strings are sequences, so they support indexing (s[i]) and slicing (s[start:stop:step]). Indices are zero-based; negative indices count from the end.

Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2

Slicing never raises IndexError, even with out-of-range bounds. It just returns whatever overlaps.

Code Block
Python 3.13.2

Unicode and len(): the emoji surprise

In Python 3, len(s) returns the number of Unicode code points, not bytes. Most characters are one code point, but some emoji and complex scripts can surprise you:

print(len("👍"))         # 1 (single code point)
print(len("👨‍👩‍👧‍👦"))      # 7 (family emoji is a sequence of code points + zero-width joiners)

If you need byte length, encode first: len(s.encode("utf-8")).

Strings are immutable

You cannot mutate a string in place. Methods like upper(), replace(), and strip() return new strings.

Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2

Immutability gotcha

Because strings are immutable, repeatedly concatenating with += in a loop is O(n²)—each operation creates a new string and copies everything.

Bad:

result = ""
for i in range(1000):
    result += str(i)  # creates a new string each time

Good:

parts = []
for i in range(1000):
    parts.append(str(i))
result = "".join(parts)

str.join() is the idiomatic way to build a string from many pieces.

Common methods

A selection of methods you'll use constantly:

Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2

Formatting: f-strings (the killer feature)

f-strings (Python 3.6+) are the modern, recommended way to build strings. Put any expression inside { ... }.

Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2

f-string format mini-language

The part after : in {value:format} is a powerful mini-language:

  • .Nf — N decimal places for floats
  • >width — right-align in width
  • <width — left-align
  • ^width — center
  • , — thousands separator
  • 0Nf — zero-pad
  • % — multiply by 100 and add percent sign

Full spec: Format Specification Mini-Language.

Other formatting styles you'll see in older code:

Code Block
Python 3.13.2

Concatenation and repetition

Code Block
Python 3.13.2

Bytes vs strings

str holds Unicode code points; bytes holds raw 8-bit values. Use .encode() to go from str to bytes and .decode() to go back. The default codec is UTF-8.

Code Block
Python 3.13.2
Code Block
Python 3.13.2

str vs bytes: a common source of bugs

File I/O, network I/O, and many libraries return bytes, not str. If you try to concatenate str and bytes, you'll get a TypeError. Always decode bytes to strings before working with text:

response = b"Hello"  # from a network request
# Bad: "Greeting: " + response  # TypeError
# Good: "Greeting: " + response.decode("utf-8")

Challenges

Challenge
Python 3.13.2
Smart title-case

Define a function format_name(first, last) that returns the name in the form "Last, First", with both names title-cased and any surrounding whitespace stripped. For example, format_name(" ada", "LOVELACE ") should return "Lovelace, Ada".

Challenge
Python 3.13.2
Palindrome checker

Write a function is_palindrome(s) that returns True if s reads the same forward and backward, ignoring case and any non-alphanumeric characters. For example, "A man, a plan, a canal: Panama" is a palindrome.

Challenge
Python 3.13.2
URL slug generator

Write a function slugify(text) that converts a string to a URL-friendly "slug": lowercase, spaces replaced with hyphens, only alphanumerics and hyphens allowed. For example, slugify("Hello World!") returns "hello-world".

Check your understanding

QuestionSelect one

What does "abcdef"[1:5:2] evaluate to?

"bcd"

"bd"

"ace"

An IndexError

QuestionSelect one

Which statement about string immutability is true?

s.upper() changes s to uppercase.

You can mutate a string by assigning to an index: s[0] = "H".

To "change" a string, you must rebind the variable to a new string.

Immutability means you can't create new strings.

QuestionSelect one

What does f"{123:05d}" produce?

"123"

"00123"

"123.00"

An error

QuestionSelect one

Which approach builds a string from a list of 1000 items without the O(n²) cost of repeated concatenation?

result = ""; for x in items: result += str(x)

result = sum(str(x) for x in items)

result = "".join(str(x) for x in items)

result = "".add(str(x) for x in items)

Next: booleans, comparisons, and Python's short-circuiting logical operators.

On this page