CMU 15-112: Fundamentals of Programming and Computer Science
Class Notes: Strings
- String Literals
- Some String Constants
- Some String Operators
- Looping over Strings
- Example: isPalindrome
- Strings are Immutable
- Some String-related Built-In Functions
- Some String Methods
- String Formatting
- Basic File IO
- String Literals
- Four kinds of quotes
# single-quoted or double-quoted strings are the most common print('single-quotes') print("double-quotes") # triple-qouted strings are less common (though see next section for a typical use) print('''triple single-quotes''') print("""triple double-quotes""") - Newlines in strings
print("abc\ndef") # \n is a single newline character print("""abc def""") print("""\ You can use a backslash at the end of a line in a string to exclude the newline after it. This should almost never be used, but one good use of it is in this example, at the start of a multi-line string, so the whole string can be entered with the same indentation (none, that is). """) - More Escape Sequences
print("Double-quote: \"") print("Backslash: \\") print("Newline (in brackets): [\n]") print("Tab (in brackets): [\t]") print("These items are tab-delimited, 3-per-line:") print("abc\tdef\tg\nhi\tj\\\tk\n---")
An escape sequence produces a single character:
s = "a\\b\"c\td" print("s =", s) print("len(s) =", len(s)) - String Literals as Multi-line Comments
""" Python does not have multiline comments, but you can do something similar by using a top-level multiline string, such as this. Technically, this is not a comment, and Python will evaluate this string, but then ignore it and garbage collect it! """ print("wow!")
- Four kinds of quotes
- Some String Constants
import string print(string.ascii_letters) # abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ print(string.ascii_lowercase) # abcdefghijklmnopqrstuvwxyz print("-----------") print(string.ascii_uppercase) # ABCDEFGHIJKLMNOPQRSTUVWXYZ print(string.digits) # 0123456789 print("-----------") print(string.punctuation) # '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' print(string.printable) # digits + letters + punctuation + whitespace print("-----------") print(string.whitespace) # space + tab + linefeed + return + ...
- Some String Operators
- String + and *
print("abc" + "def") print("abc" * 3) print("abc" + 3) # error - The in operator
print("ring" in "strings") print("wow" in "amazing!") print("Yes" in "yes!") print("" in "No way!") - String indexing and slicing
- Indexing a single character
s = "abcdefgh" print(s) print(s[0]) print(s[1]) print(s[2]) print("-----------") print(s[len(s)-1]) print(s[len(s)]) # crashes (string index out of range) - Negative indexes
s = "abcdefgh" print(s) print(s[-1]) print(s[-2]) - Slicing a range of characters
s = "abcdefgh" print(s) print(s[0:3]) print(s[1:3]) print("-----------") print(s[2:3]) print(s[3:3]) - Slicing with default parameters
s = "abcdefgh" print(s) print(s[3:]) print(s[:3]) print(s[:]) - Slicing with a step parameter
print("This is not as common, but perfectly ok.") s = "abcdefgh" print(s) print(s[1:7:2]) print(s[1:7:3]) - Reversing a string
s = "abcdefgh" print("This works, but is confusing:") print(s[::-1]) print("This also works, but is still confusing:") print("".join(reversed(s))) print("Best way: write your own reverseString() function:") def reverseString(s): return s[::-1] print(reverseString(s)) # crystal clear!
- Indexing a single character
- String + and *
- Looping over Strings
- "for" loop with indexes
s = "abcd" for i in range(len(s)): print(i, s[i]) - "for" loop without indexes
s = "abcd" for c in s: print(c) - "for" loop with split
names = "fred,wilma,betty,barney" for name in names.split(","): print(name) - "for" loop with splitlines
# quotes from brainyquote.com quotes = """\ Dijkstra: Simplicity is prerequisite for reliability. Knuth: If you optimize everything, you will always be unhappy. Dijkstra: Perfecting oneself is as much unlearning as it is learning. Knuth: Beware of bugs in the above code; I have only proved it correct, not tried it. Dijkstra: Computer science is no more about computers than astronomy is about telescopes. """ for line in quotes.splitlines(): if (line.startswith("Knuth")): print(line)
- "for" loop with indexes
- Example: isPalindrome
# There are many ways to write isPalindrome(s) # Here are several. Which way is best? def reverseString(s): return s[::-1] def isPalindrome1(s): return (s == reverseString(s)) def isPalindrome2(s): for i in range(len(s)): if (s[i] != s[len(s)-1-i]): return False return True def isPalindrome3(s): for i in range(len(s)): if (s[i] != s[-1-i]): return False return True def isPalindrome4(s): while (len(s) > 1): if (s[0] != s[-1]): return False s = s[1:-1] return True print(isPalindrome1("abcba"), isPalindrome1("abca")) print(isPalindrome2("abcba"), isPalindrome2("abca")) print(isPalindrome3("abcba"), isPalindrome3("abca")) print(isPalindrome4("abcba"), isPalindrome4("abca"))
- Strings are Immutable
- You cannot change strings! They are immutable.
s = "abcde" s[2] = "z" # Error! Cannot assign into s[i] - Instead, you must create a new string
s = "abcde" s = s[:2] + "z" + s[3:] print(s)
- You cannot change strings! They are immutable.
- str() and len()
name = input("Enter your name: ") print("Hi, " + name + ". Your name has " + str(len(name)) + " letters!") - chr() and ord()
print(ord("A")) # 65 print(chr(65)) # "A" print(chr(ord("A")+1)) # ? - eval()
# eval() works but you should not use it! s = "(3**2 + 4**2)**0.5" print(eval(s)) # why not? Well... s = "reformatMyHardDrive()" print(eval(s)) # no such function! But what if there was?
- Character types: isalnum(), isalpha(), isdigit(), islower(), isspace(), isupper()
# Run this code to see a table of isX() behaviors def p(test): print("True " if test else "False ", end="") def printRow(s): print(" " + s + " ", end="") p(s.isalnum()) p(s.isalpha()) p(s.isdigit()) p(s.islower()) p(s.isspace()) p(s.isupper()) print() def printTable(): print(" s isalnum isalpha isdigit islower isspace isupper") for s in "ABCD,ABcd,abcd,ab12,1234, ,AB?!".split(","): printRow(s) printTable() - String edits: lower(), upper(), replace(), strip()
print("This is nice. Yes!".lower()) print("So is this? Sure!!".upper()) print(" Strip removes leading and trailing whitespace only ".strip()) print("\n\n You can choose which type of whitespace you want to remove!\n".strip()) print("This is nice. Really nice.".replace("nice", "sweet")) print("This is nice. Really nice.".replace("nice", "sweet", 1)) # count = 1 print("----------------") s = "This is so so fun!" t = s.replace("so ", "") print(t) print(s) # note that s is unmodified (strings are immutable!) - Substring search: count(), startswith(), endswith(), find(), index()
print("This is a history test".count("is")) # 3 print("This IS a history test".count("is")) # 2 print("-------") print("Dogs and cats!".startswith("Do")) # True print("Dogs and cats!".startswith("Don't")) # False print("-------") print("Dogs and cats!".endswith("!")) # True print("Dogs and cats!".endswith("rats!")) # False print("-------") print("Dogs and cats!".find("and")) # 5 print("Dogs and cats!".find("or")) # -1 print("-------") print("Dogs and cats!".index("and")) # 5 print("Dogs and cats!".index("or")) # crash!
format a string with %s
breed = "beagle"
print("Did you see a %s?" % breed)
format an integer with %d
dogs = 42
print("There are %d dogs." % dogs)
format a float with %f
grade = 87.385
print("Your current grade is %f!" % grade)
format a float with %.[precision]f
grade = 87.385
print("Your current grade is %0.1f!" % grade)
format multiple values
dogs = 42
cats = 18
exclamation = "Wow"
print("There are %d dogs and %d cats. %s!!!" % (dogs, cats, exclamation))
format right-aligned with %[minWidth]
dogs = 42
cats = 3
print("%10s %10s" % ("dogs", "cats"))
print("%10d %10d" % (dogs, cats))
format left-aligned with %-[minWidth]
dogs = 42
cats = 3
print("%-10s %-10s" % ("dogs", "cats"))
print("%-10d %-10d" % (dogs, cats))
# Note: As this requires read-write access to your hard drive,
# this will not run in the browser in Brython.
def readFile(path):
with open(path, "rt") as f:
return f.read()
def writeFile(path, contents):
with open(path, "wt") as f:
f.write(contents)
contentsToWrite = "This is a test!\nIt is only a test!"
writeFile("foo.txt", contentsToWrite)
contentsRead = readFile("foo.txt")
assert(contentsRead == contentsToWrite)
print("Open the file foo.txt and verify its contents.")