By and large, strings are fairly easy to use in Python. Perhaps the most complicated thing about them is that there are so many ways to write them in your code:
Single quotes: 'spa"m'
Double quotes: "spa'm"
Triple quotes: '''... spam ...''', """... spam ..."""
Escape sequences: "s\tp\na\0m"
Raw strings: r"C:\new\test.spm"
Bytes literals in 3.X and 2.6+ (see Chapter 4, Chapter 37): b'sp\x01am'
Unicode literals in 2.X and 3.3+ (see Chapter 4, Chapter 37): u'eggs\u0020spam'
The single- and double-quoted forms are by far the most common; the others serve specialized roles, and we’re postponing further discussion of the last two advanced forms until Chapter 37. Let’s take a quick look at all the other options in turn.
Around Python strings, single- and double-quote characters are interchangeable. That is, string literals can be written enclosed in either two single or two double quotes—the two forms work the same and return the same type of object. For example, the following two strings are identical, once coded:
>>> 'shrubbery', "shrubbery"
('shrubbery', 'shrubbery')
The reason for supporting both is that it allows you to embed a quote character of the other variety inside a string without escaping it with a backslash. You may embed a single-quote character in a string enclosed in double-quote characters, and vice versa:
>>> 'knight"s', "knight's"
('knight"s', "knight's")
This book generally prefers to use single quotes around strings just because they are marginally easier to read, except in cases where a single quote is embedded in the string. This is a purely subjective style choice, but Python displays strings this way too and most Python programmers do the same today, so you probably should too.
Note that the comma is important here. Without it, Python automatically concatenates adjacent string literals in any expression, although it is almost as simple to add a + operator between them to invoke concatenation explicitly (as we’ll see in Chapter 12, wrapping this form in parentheses also allows it to span multiple lines):
>>>title = "Meaning " 'of' " Life"# Implicit concatenation >>>title'Meaning of Life'
Adding commas between these strings would result in a tuple, not a string. Also notice in all of these outputs that Python prints strings in single quotes unless they embed one. If needed, you can also embed quote characters by escaping them with backslashes:
>>> 'knight\'s', "knight\"s"
("knight's", 'knight"s')
To understand why, you need to know how escapes work in general.
The last example embedded a quote inside a string by preceding it with a backslash. This is representative of a general pattern in strings: backslashes are used to introduce special character codings known as escape sequences.
Escape sequences let us embed characters in strings that cannot easily be typed on a keyboard. The character \, and one or more characters following it in the string literal, are replaced with a single character in the resulting string object, which has the binary value specified by the escape sequence. For example, here is a five-character string that embeds a newline and a tab:
>>> s = 'a\nb\tc'
The two characters \n stand for a single character—the binary value of the newline character in your character set (in ASCII, character code 10). Similarly, the sequence \t is replaced with the tab character. The way this string looks when printed depends on how you print it. The interactive echo shows the special characters as escapes, but print interprets them instead:
>>>s'a\nb\tc' >>>print(s)a b c
To be completely sure how many actual characters are in this string, use the built-in len function—it returns the actual number of characters in a string, regardless of how it is coded or displayed:
>>> len(s)
5
This string is five characters long: it contains an ASCII a, a newline character, an ASCII b, and so on.
If you’re accustomed to all-ASCII text, it’s tempting to think of this result as meaning 5 bytes too, but you probably shouldn’t. Really, “bytes” has no meaning in the Unicode world. For one thing, the string object is probably larger in memory in Python.
More critically, string content and length both reflect code points (identifying numbers) in Unicode-speak, where a single character does not necessarily map directly to a single byte, either when encoded in files or when stored in memory. This mapping might hold true for simple 7-bit ASCII text, but even this depends on both the external encoding type and the internal storage scheme used. Under UTF-16, for example, ASCII characters are multiple bytes in files, and they may be 1, 2, or 4 bytes in memory depending on how Python allocates their space. For other, non-ASCII text, whose characters’ values might be too large to fit in an 8-bit byte, the character-to-byte mapping doesn’t apply at all.
In fact, 3.X defines str strings formally as sequences of Unicode code points, not bytes, to make this clear. There’s more on how strings are stored internally in Chapter 37 if you care to know. For now, to be safest, think characters instead of bytes in strings. Trust me on this; as an ex-C programmer, I had to break the habit too!
Note that the original backslash characters in the preceding result are not really stored with the string in memory; they are used only to describe special character values to be stored in the string. For coding such special characters, Python recognizes a full set of escape code sequences, listed in Table 7-2.
Table 7-2. String backslash characters
|
Escape |
Meaning |
|---|---|
|
|
Ignored (continuation line) |
|
|
Backslash (stores one |
|
|
Single quote (stores |
|
|
Double quote (stores |
|
|
Bell |
|
|
Backspace |
|
|
Formfeed |
|
|
Newline (linefeed) |
|
|
Carriage return |
|
|
Horizontal tab |
|
|
Vertical tab |
|
|
Character with hex value |
|
|
Character with octal value |
|
|
Null: binary 0 character (doesn’t end string) |
|
|
Unicode database ID |
|
|
Unicode character with 16-bit hex value |
|
|
Unicode character with 32-bit hex value[a] |
|
|
Not an escape (keeps both |
|
[a] The |
|
Some escape sequences allow you to embed absolute binary values into the characters of a string. For instance, here’s a five-character string that embeds two characters with binary zero values (coded as octal escapes of one digit):
>>>s = 'a\0b\0c'>>>s'a\x00b\x00c' >>>len(s)5
In Python, a zero (null) character like this does not terminate a string the way a “null byte” typically does in C. Instead, Python keeps both the string’s length and text in memory. In fact, no character terminates a string in Python. Here’s a string that is all absolute binary escape codes—a binary 1 and 2 (coded in octal), followed by a binary 3 (coded in hexadecimal):
>>>s = '\001\002\x03'>>>s'\x01\x02\x03' >>>len(s)3
Notice that Python displays nonprintable characters in hex, regardless of how they were specified. You can freely combine absolute value escapes and the more symbolic escape types in Table 7-2. The following string contains the characters “spam”, a tab and newline, and an absolute zero value character coded in hex:
>>>S = "s\tp\na\x00m">>>S's\tp\na\x00m' >>>len(S)7 >>>print(S)s p a m
This becomes more important to know when you process binary data files in Python. Because their contents are represented as strings in your scripts, it’s OK to process binary files that contain any sorts of binary byte values—when opened in binary modes, files return strings of raw bytes from the external file (there’s much more on files in Chapter 4, Chapter 9, and Chapter 37).
Finally, as the last entry in Table 7-2 implies, if Python does not recognize the character after a \ as being a valid escape code, it simply keeps the backslash in the resulting string:
>>>x = "C:\py\code"# Keeps \ literally (and displays it as \\) >>>x'C:\\py\\code' >>>len(x)10
However, unless you’re able to commit all of Table 7-2 to memory (and there are arguably better uses for your neurons!), you probably shouldn’t rely on this behavior. To code literal backslashes explicitly such that they are retained in your strings, double them up (\\ is an escape for one \) or use raw strings; the next section shows how.
As we’ve seen, escape sequences are handy for embedding special character codes within strings. Sometimes, though, the special treatment of backslashes for introducing escapes can lead to trouble. It’s surprisingly common, for instance, to see Python newcomers in classes trying to open a file with a filename argument that looks something like this:
myfile = open('C:\new\text.dat', 'w')
thinking that they will open a file called text.dat in the directory C:\new. The problem here is that \n is taken to stand for a newline character, and \t is replaced with a tab. In effect, the call tries to open a file named C:(newline)ew(tab)ext.dat, with usually less-than-stellar results.
This is just the sort of thing that raw strings are useful for. If the letter r (uppercase or lowercase) appears just before the opening quote of a string, it turns off the escape mechanism. The result is that Python retains your backslashes literally, exactly as you type them. Therefore, to fix the filename problem, just remember to add the letter r on Windows:
myfile = open(r'C:\new\text.dat', 'w')
Alternatively, because two backslashes are really an escape sequence for one backslash, you can keep your backslashes by simply doubling them up:
myfile = open('C:\\new\\text.dat', 'w')
In fact, Python itself sometimes uses this doubling scheme when it prints strings with embedded backslashes:
>>>path = r'C:\new\text.dat'>>>path# Show as Python code 'C:\\new\\text.dat' >>>print(path)# User-friendly format C:\new\text.dat >>>len(path)# String length 15
As with numeric representation, the default format at the interactive prompt prints results as if they were code, and therefore escapes backslashes in the output. The print statement provides a more user-friendly format that shows that there is actually only one backslash in each spot. To verify this is the case, you can check the result of the built-in len function, which returns the number of characters in the string, independent of display formats. If you count the characters in the print(path) output, you’ll see that there really is just 1 character per backslash, for a total of 15.
Besides directory paths on Windows, raw strings are also commonly used for regular expressions (text pattern matching, supported with the re module introduced in Chapter 4 and Chapter 37). Also note that Python scripts can usually use forward slashes in directory paths on Windows and Unix because Python tries to interpret paths portably (i.e., 'C:/new/text.dat' works when opening files, too). Raw strings are useful if you code paths using native Windows backslashes, though.
Despite its role, even a raw string cannot end in a single backslash, because the backslash escapes the following quote character—you still must escape the surrounding quote character to embed it in the string. That is, r"...\" is not a valid string literal—a raw string cannot end in an odd number of backslashes. If you need to end a raw string with a single backslash, you can use two and slice off the second (r'1\nb\tc\\'[:-1]), tack one on manually (r'1\nb\tc' + '\\'), or skip the raw string syntax and just double up the backslashes in a normal string ('1\\nb\\tc\\'). All three of these forms create the same eight-character string containing three backslashes.
So far, you’ve seen single quotes, double quotes, escapes, and raw strings in action. Python also has a triple-quoted string literal format, sometimes called a block string, that is a syntactic convenience for coding multiline text data. This form begins with three quotes (of either the single or double variety), is followed by any number of lines of text, and is closed with the same triple-quote sequence that opened it. Single and double quotes embedded in the string’s text may be, but do not have to be, escaped—the string does not end until Python sees three unescaped quotes of the same kind used to start the literal. For example (the “...” here is Python’s prompt for continuation lines outside IDLE: don’t type it yourself):
>>>mantra = """Always look...on the bright...side of life.""">>> >>>mantra'Always look\n on the bright\nside of life.'
This string spans three lines. As we learned in Chapter 3, in some interfaces, the interactive prompt changes to ... on continuation lines like this, but IDLE simply drops down one line; this book shows listings in both forms, so extrapolate as needed. Either way, Python collects all the triple-quoted text into a single multiline string, with embedded newline characters (\n) at the places where your code has line breaks. Notice that, as in the literal, the second line in the result has leading spaces, but the third does not—what you type is truly what you get. To see the string with the newlines interpreted, print it instead of echoing:
>>> print(mantra)
Always look
on the bright
side of life.
In fact, triple-quoted strings will retain all the enclosed text, including any to the right of your code that you might intend as comments. So don’t do this—put your comments above or below the quoted text, or use the automatic concatenation of adjacent strings mentioned earlier, with explicit newlines if desired, and surrounding parentheses to allow line spans (again, more on this latter form when we study syntax rules in Chapter 10 and Chapter 12):
>>>menu = """spam # comments here added to string!...eggs # ditto...""">>>menu'spam # comments here added to string!\neggs # ditto\n' >>>menu = (..."spam\n" # comments here ignored..."eggs\n" # but newlines not automatic...)>>>menu'spam\neggs\n'
Triple-quoted strings are useful anytime you need multiline text in your program; for example, to embed multiline error messages or HTML, XML, or JSON code in your Python source code files. You can embed such blocks directly in your scripts by triple-quoting without resorting to external text files or explicit concatenation and newline characters.
Triple-quoted strings are also commonly used for documentation strings, which are string literals that are taken as comments when they appear at specific points in your file (more on these later in the book). These don’t have to be triple-quoted blocks, but they usually are to allow for multiline comments.
Finally, triple-quoted strings are also sometimes used as a “horribly hackish” way to temporarily disable lines of code during development (OK, it’s not really too horrible, and it’s actually a fairly common practice today, but it wasn’t the intent). If you wish to turn off a few lines of code and run your script again, simply put three quotes above and below them, like this:
X = 1
"""
import os # Disable this code temporarily
print(os.getcwd())
"""
Y = 2
I said this was hackish because Python really might make a string out of the lines of code disabled this way, but this is probably not significant in terms of performance. For large sections of code, it’s also easier than manually adding hash marks before each line and later removing them. This is especially true if you are using a text editor that does not have support for editing Python code specifically. In Python, practicality often beats aesthetics.