Python Strings: Creating, Indexing and Slicing

A string is an immutable ordered sequence of characters. Indexing reaches one character, slicing reaches a range, and negative numbers count from the right.

Creating strings

single = 'Python'
double = "Python"
mixed  = "It's fine"          # double quotes let you keep the apostrophe
escaped = 'It\'s fine'         # or escape it

triple = """A string that
spans several lines
without any escaping."""

Single and double quotes are identical in meaning. Choose whichever avoids escaping. Triple quotes preserve line breaks exactly and are also how docstrings are written.

Escape sequences

SequenceMeaning
\nNewline
\tTab
\\A single backslash
\' \"A quote inside the same kind of quote
\u20b9A character by its Unicode code point
print("Line one\nLine two")
print("Name:\tMeera")
print("C:\\Users\\Admin")        # one backslash each in the output
print("\u20b9250")               # a rupee sign followed by 250

Raw strings

path = r"C:\Users\Admin\notes"     # backslashes stay literal
pattern = r"\d+\s\w+"              # essential for regular expressions

print(path)
print(len("\n"), len(r"\n"))       # 1 2

A raw string turns off escape processing. It is the normal way to write file paths on Windows and regular expression patterns anywhere.

Indexing

text = "Python"

print(text[0])      # P
print(text[3])      # h
print(text[-1])     # n   last character
print(text[-2])     # o
# print(text[10])   # IndexError: string index out of range
  P    y    t    h    o    n
  0    1    2    3    4    5      forward index
 -6   -5   -4   -3   -2   -1      backward index

Indexing always returns a string of length one. Python has no separate character type.

Slicing

The form is text[start:stop:step]. start is included, stop is excluded.

text = "Programming"

print(text[0:7])      # Program
print(text[:7])       # Program      - start defaults to 0
print(text[7:])       # ming         - stop defaults to the end
print(text[:])        # Programming  - a full copy
print(text[-4:])      # ming
print(text[:-4])      # Program
print(text[::2])      # Pormig       - every second character
print(text[::-1])     # gnimmargorP  - reversed
Slicing never raises IndexError. "abc"[10:20] quietly returns "". Indexing out of range does raise. That asymmetry is intentional and worth remembering.

Why stop is excluded

text = "Programming"

print(len(text[0:7]))          # 7 - the length equals stop minus start
print(text[:3] + text[3:])     # Programming - the two halves reassemble exactly

Both properties fail if stop were included. This is the same convention range() uses.

Slicing with a negative step

text = "Programming"

print(text[::-1])       # gnimmargorP
print(text[5:1:-1])     # marg   - walks backwards from index 5 down to 2
print(text[::-2])       # gimagr

Immutability

text = "hello"
# text[0] = "H"        # TypeError: 'str' object does not support item assignment

text = "H" + text[1:]  # build a new string instead
print(text)            # Hello

original = "hello"
upper = original.upper()
print(original, upper)     # hello HELLO - the original is untouched

Every string method returns a new string. None of them modifies the original, because none of them can. Forgetting to assign the result is the single most common string mistake:

name = "  meera  "
name.strip()              # the result is computed and thrown away
print(repr(name))         # '  meera  ' - unchanged

name = name.strip()       # correct
print(repr(name))         # 'meera'

Length and iteration

text = "Python"

print(len(text))           # 6

for character in text:
    print(character, end=" ")
print()

for index, character in enumerate(text):
    print(index, character)

Strings are Unicode

text = "नमस्ते"
print(len(text))            # counts code points, not bytes

print(ord("A"))             # 65
print(chr(65))              # A
print(ord("₹"))             # 8377

encoded = "café".encode("utf-8")
print(encoded)              # b'caf\xc3\xa9'
print(len("café"), len(encoded))   # 4 5
print(encoded.decode("utf-8"))     # café

A Python 3 string is a sequence of Unicode code points. Bytes are a different type, produced by encode and turned back by decode. Files and networks carry bytes; your program works in text. Convert at the boundary and nowhere else.

Common mistakes

  • Calling a string method and not assigning the result.
  • Trying to assign to text[0].
  • Expecting text[0:5] to include index 5.
  • Writing a Windows path without a raw string, so \\n or \\t becomes a control character.
  • Confusing len of a string with the number of bytes it occupies.
  • Building a long string by repeated += in a loop; use "".join(parts) instead.

Best practices

  • Pick one quote style per project and switch only to avoid escaping.
  • Use raw strings for paths and regular expression patterns without exception.
  • Use slicing rather than a loop when you want a portion of a string.
  • Remember that text[:] is a copy, and that copying an immutable object is rarely necessary.
  • Decode bytes into text as early as possible, encode as late as possible.

Practice

  1. Given "Programming", produce "gram", "Pormig", "gnimmargorP" and "ming" with slices only.
  2. Write a function that checks whether a word is a palindrome, ignoring case, in one line.
  3. Explain why "abc"[5] raises but "abc"[5:9] does not.
  4. Print the first and last three characters of any string, handling strings shorter than six characters sensibly.
  5. Explain the difference between len("café") and len("café".encode("utf-8")).

Conclusion

Strings are immutable sequences. Index for one character, slice for a range, remember that stop is excluded and that slices never raise, and always assign the result of a string method to something.

Written by Lorens Mishra

Default administrator account created by the installer.

Continue reading

All Python notes →

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.