PYTHON / STRINGS
Escape sequences and raw strings
Read and write Python literals that contain backslashes, knowing which escapes exist, what r"..." changes, and how many characters result.
What you will learn
- Predict the characters a literal produces from its escape sequences
- Use r"..." for regex patterns and Windows paths, and say why it helps
- Distinguish what print shows from what repr and len reveal about backslashes
- Know why a raw string cannot end in a single backslash
Understanding Escape sequences and raw strings
A backslash inside a normal string literal is an instruction to the compiler, not a character in the result. When Python parses "Tab:\tEnd" it replaces the two source characters backslash and t with one character, U+0009. The value stored at runtime has no backslash in it at all, which is why len("\t") is 1 and why there is no later "unescaping" step you can turn off. The recognised sequences are a fixed short list: \n, \t, \r, \\, \', \", \0, \a, \b, \f, \v, plus the numeric forms \xhh, \ooo, \uXXXX, \UXXXXXXXX and the name form \N{...}.
Because that list is fixed, a backslash followed by something else is not translated. "\d" stays as two characters, backslash and d, but Python emits a SyntaxWarning for it, since such a sequence is almost always a mistake and future versions reserve the right to make it an error. Prefixing the literal with r turns the translation off entirely: in r"C:\new", the backslashes and the letters n and e are all kept as written. The r affects only how the source text is read; the object produced is an ordinary str with no memory of how it was written.
The one thing r does not change is how the parser finds the closing quote. It still treats a backslash as protecting the next character from ending the literal, so r"C:\" is an unterminated string and a SyntaxError, even though a raw string can happily contain a backslash anywhere else. This is the practical rule for choosing a form: use r"..." when the backslashes are meant for another language such as a regular expression or a Windows path, use plain literals when you actually want a tab or newline character, and check with repr or len whenever you are unsure which you got.
s = "Tab:\tEnd"
print(s)
print(len("\t"), len(r"\t"))
path = "C:\new\table.txt"
print(path)
print(r"C:\new\table.txt")
print("He said \"hi\" and left\\")
print(repr(r"\d+\s"))Escape sequences are resolved when the source is compiled, so a literal's value contains characters, not backslashes, and the r prefix simply switches that translation off.
Worked examples
Numeric and named character escapes
Shows the escape forms that build a character from a code point or a Unicode name.
print("\x41\x42")
print("\N{GREEK SMALL LETTER ALPHA}\u00e9")
print(len("\u00e9"), len("e\u0301"))
print("caf\u00e9" == "caf\N{LATIN SMALL LETTER E WITH ACUTE}")Example explained
Line 1\x41 consumes exactly two hex digits and yields the character at that code point, so the first line is AB.
Line 2\N{...} looks a character up by its official Unicode name; \u00e9 names the same é numerically.
Line 3"\u00e9" is one character but "e\u0301" is two, an e plus a combining acute accent, although both display as é.
Line 4The comparison is True because both literals compile to the identical one-character string object value.
Why regex patterns use r"..."
Demonstrates that the regex engine needs to receive a real backslash, which r"..." delivers without doubling.
import re
text = "cat category cat."
print(re.findall(r"\bcat\b", text))
print(re.findall("\\bcat\\b", text))
print(r"\b" == "\\b", len(r"\b"))Example explained
Line 1r"\bcat\b" hands re the characters backslash, b, c, a, t, backslash, b, which re reads as a word boundary around cat.
Line 2"\\bcat\\b" produces exactly the same characters the long way, which is why both calls return the same matches.
Line 3Written as "\b" without doubling or the r prefix, the literal would be a single backspace character and would match nothing.
Line 4"category" is skipped because there is no word boundary between cat and the following e.
print, repr and len disagree on purpose
Separates the characters a string holds from the literal syntax repr uses to display it.
s = "a\tb\\c"
print(s)
print(repr(s))
print(len(s), s.count("\\"))Example explained
Line 1print writes the stored characters, so the tab shows as blank space and the escaped backslash as one backslash.
Line 2repr rebuilds a valid literal, re-escaping the tab as \t and the backslash as \\, so the display is longer than the value.
Line 3len is 5 because each two-character escape in the source contributed exactly one character.
Line 4s.count("\\") finds one backslash; the search argument itself has to be doubled to mean a single backslash.
Important notes
The r prefix is source syntax only; r"\n" and "\\n" produce equal str objects, and nothing at runtime can tell which form was typed.
Bytes literals have their own escape list: \x works, but \u, \U and \N{...} are not escapes in b"..." and stay as plain characters.
Common mistakes
Pasting a Windows path as "C:\new\table.txt": no error is raised, but \n and \t become a newline and a tab, so the path silently refers to a filename that does not exist.
Assuming r"\n" is somehow still a newline in disguise; it is two characters, so writing it to a file gives the literal text \n and open(r"data\n") looks for a filename containing a backslash.
Ending a raw string with a single backslash, as in r"C:\path\", which is a SyntaxError because the backslash stops the quote from closing the literal.
Try it yourself
Change, predict, then run
Create two variables holding the same value, one as a raw literal and one with doubled backslashes, for the Windows path C:\Users\new\test.csv, then print len() of each and assert they are equal.
Open the Python workspaceCheck your understanding
open(r"C:\temp\new.txt") finds the file but open("C:\temp\new.txt") fails. Why?
- In the non-raw literal, \t and \n are turned into a tab and a newline while compiling, so the path never contains those letters
- The r prefix tells Python to apply Windows path rules instead of POSIX ones
- open() accepts backslashes only in raw strings, and rejects them in ordinary strings
- The r prefix escapes the backslashes at runtime, doubling them just before the call
Show answer
The failure happens at compile time: \t and \n are valid escapes, so the second literal's value is "C:" + tab + "emp" + newline + "ew.txt", a path no file matches. The runtime-doubling option is wrong because r changes nothing after compilation; both forms produce a plain str and open() cannot tell them apart.