Strings

One place where the Python language really shines is in the manipulation of strings. This section will cover some of Python's built-in string methods and formatting operations.

Such string manipulation patterns come up often in the context of data science work.

String syntax

Strings in Python can be defined using either single or double quotations. They are functionally equivalent.

Python
x = 'Pluto is a planet'
y = "Pluto is a planet"

x == y

Out

Python
True

Double quotes are convenient if your string contains a single quote character (that is, representing an apostrophe).

Similarly, it's easy to create a string that contains double-quotes if you wrap it in single quotes.

Python
print("Pluto's a planet!")
print('My dog is named "Pluto"')

Out

Python
Pluto's a planet!
My dog is named "Pluto"

If we try to put a single quote character inside a single-quoted string, Python gets confused.

Python
'Pluto's a planet!'
Python
  File "/tmp/ipykernel_19/1561186517.py", line 1
    'Pluto's a planet!'
           ^
SyntaxError: invalid syntax

We can fix this by "escaping" the single quote with a backslash.

Python
'Pluto\'s a planet!'

Out

Python
"Pluto's a planet!"

The table below summarizes some important uses of the backslash character.

What you type...What you getexampleprint(example)
\'''What\'s up?'What's up?
\"""That's \"cool\""That's "cool."
\\\"Look, a mountain: /\\"Look, a mountain: /\
\n "1\n2 3"1
2 3

The last sequence, \n, represents the newline character. It causes Python to start a new line.

Python
hello = "hello\nworld"
print(hello)
Python
hello
world

In addition, Python's triple quote syntax for strings lets us include newlines literally (i.e., by just hitting 'Enter' on our keyboard, rather than using the special '\n' sequence). We've already seen this in the docstrings we use to document our functions, but we can use it anywhere we want to define a string.

Python
triplequoted_hello = """hello
world"""
print(triplequoted_hello)
triplequoted_hello == hello
Python
hello
world

Out

Python
True

The print() function automatically adds a newline character unless we specify a value for the keyword argument end other than the default value of '\n'.

Python
print("hello")
print("world")
print("hello", end='')
print("pluto", end='')
Python
hello
world
hellopluto

Strings are sequences

Strings can be thought of as sequences of characters. Almost everything we've seen that we can do to a list, we can also do to a string.

Python
# Indexing
planet = 'Pluto'
planet[0]

Out

Python
'P'
Python
# Slicing
planet[-3:]

Out

Python
'uto'
Python
# How long is this string?
len(planet)

Out

Python
5
Python
# Yes, we can even loop over them
[char+'! ' for char in planet]

Out

Python
['P! ', 'l! ', 'u! ', 't! ', 'o! ']

But a major way in which they differ from lists is that they are immutable. We can't modify them.

Python
planet[0] = 'B'
# planet.append doesn't work either
Python
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_19/2683731249.py in <module>
----> 1 planet[0] = 'B'
      2 # planet.append doesn't work either

TypeError: 'str' object does not support item assignment

String methods

Like list, the type str has lots of very useful methods. I'll show just a few examples here.

Python
# ALL CAPS
claim = "Pluto is a planet!"
claim.upper()

Out

Python
'PLUTO IS A PLANET!'
Python
# all lowercase
claim.lower()

Out

Python
'pluto is a planet!'
Python
# Searching for the first index of a substring
claim.index('plan')

Out

Python
11
Python
claim.startswith(planet)

Out

Python
True
Python
# false because of missing exclamation mark
claim.endswith('planet')

Out

Python
False

Going between strings and lists: .split() and .join()

str.split() turns a string into a list of smaller strings, breaking on whitespace by default. This is super useful for taking you from one big string to a list of words.

Out

Python
['Pluto', 'is', 'a', 'planet!']

Occasionally, you'll want to split on something other than whitespace.

Python
datestr = '1956-01-31'
year, month, day = datestr.split('-')

str.join() takes us in the other direction, sewing a list of strings up into one long string, using the string it was called on as a separator.

Python
'/'.join([month, day, year])

Out

Python
'01/31/1956'
Python
# Yes, we can put unicode characters right in our string literals :)
' 👏 '.join([word.upper() for word in words])

Out

Python
'PLUTO 👏 IS 👏 A 👏 PLANET!'

Building strings with .format()

Python lets us concatenate strings with the + operator.

Python
planet + ', we miss you.'

Out

Python
'Pluto, we miss you.'

If we want to throw in any non-string objects, we have to be careful to call str() on them first.

Python
position = 9
planet + ", you'll always be the " + position + "th planet to me."
Python
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_19/1802981568.py in <module>
      1 position = 9
----> 2 planet + ", you'll always be the " + position + "th planet to me."

TypeError: can only concatenate str (not "int") to str
Python
planet + ", you'll always be the " + str(position) + "th planet to me."

Out

Python
"Pluto, you'll always be the 9th planet to me."

This is getting hard to read and annoying to type. str.format() to the rescue.

Code
"{}, you'll always be the {}th planet to me.".format(planet, position)

Out

Python
"Pluto, you'll always be the 9th planet to me."

So much cleaner! We call .format() on a "format string", where the Python values we want to insert are represented with {} placeholders.

Notice how we didn't even have to call str() to convert position from an int. format() takes care of that for us.

If that was all that format() did, it would still be incredibly useful. But as it turns out, it can do a lot more. Here's just a taste.

Python
pluto_mass = 1.303 * 10**22
earth_mass = 5.9722 * 10**24
population = 52910390
#         2 decimal points   3 decimal points, format as percent     separate with commas
"{} weighs about {:.2} kilograms ({:.3%} of Earth's mass). It is home to {:,} Plutonians.".format(
    planet, pluto_mass, pluto_mass / earth_mass, population,
)

Out

Python
"Pluto weighs about 1.3e+22 kilograms (0.218% of Earth's mass). It is home to 52,910,390 Plutonians."
Python
# Referring to format() arguments by index, starting from 0
s = """Pluto's a {0}.
No, it's a {1}.
{0}!
{1}!""".format('planet', 'dwarf planet')
print(s)
Python
Pluto's a planet.
No, it's a dwarf planet.
planet!
dwarf planet!

Dictionaries

Dictionaries are a built-in Python data structure for mapping keys to values.

Python
numbers = {'one':1, 'two':2, 'three':3}

In this case, 'one', 'two', and 'three' are the keys, and 1, 2, and 3 are their corresponding values.

Values are accessed via square bracket syntax similar to indexing into lists and strings.

Python
numbers['one']

Out

Python
1

We can use the same syntax to add another key-value pair.

Code
numbers['eleven'] = 11
numbers

Out

Python
{'one': 1, 'two': 2, 'three': 3, 'eleven': 11}

Or to change the value associated with an existing key.

Python
numbers['one'] = 'Pluto'
numbers

Out

Python
{'one': 'Pluto', 'two': 2, 'three': 3, 'eleven': 11}

Python has dictionary comprehensions with a syntax similar to the list comprehensions we saw in the previous tutorial.

Python
planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']
planet_to_initial = {planet: planet[0] for planet in planets}
planet_to_initial

Out

Python
{'Mercury': 'M',
 'Venus': 'V',
 'Earth': 'E',
 'Mars': 'M',
 'Jupiter': 'J',
 'Saturn': 'S',
 'Uranus': 'U',
 'Neptune': 'N'}

The in operator tells us whether something is a key in the dictionary.

Python
'Saturn' in planet_to_initial

Out

Python
True
Python
'Betelgeuse' in planet_to_initial

Out

Python
False

A for loop over a dictionary will loop over its keys.

Python
for k in numbers:
    print("{} = {}".format(k, numbers[k]))
Python
one = Pluto
two = 2
three = 3
eleven = 11

We can access a collection of all the keys or all the values with dict.keys() and dict.values(), respectively.

Python
# Get all the initials, sort them alphabetically, and put them in a space-separated string.
' '.join(sorted(planet_to_initial.values()))

Out

Python
'E J M M N S U V'

The very useful dict.items() method lets us iterate over the keys and values of a dictionary simultaneously. (In Python jargon, an item refers to a key-value pair)

Python
for planet, initial in planet_to_initial.items():
    print("{} begins with \"{}\"".format(planet.rjust(10), initial))
Python
Mercury begins with "M"
     Venus begins with "V"
     Earth begins with "E"
      Mars begins with "M"
   Jupiter begins with "J"
    Saturn begins with "S"
    Uranus begins with "U"
   Neptune begins with "N"