4. Strings

Strings are among the most popular types in Python. We can create them simply by enclosing characters in quotes.  Strings, which can be expressed in several ways. They can be enclosed in single quotes ('...') or double quotes ("...") with the same result. \ can be used to preserve the use of the string quotes.

'green eggs'          # single quotes
'ain\'t ham'          # use \' to preserve the single quote
"isn't it, he said"   # or use double quotes instead
'"Yes," she said.'

In the python interpreter, the output string is enclosed in quotes ('...'). While it might sometimes look different from the input, the two strings are equivalent. The string is enclosed in double quotes if the string contains a single quote and no double quotes, otherwise it is enclosed in single quotes. The print() function produces a more readable output, by omitting the enclosing quotes and by printing preserved and special characters:

'"doesn\'t, matter" he said.'
print('"doesn\'t, matter" he said.')

In some special cases, if you don’t want characters prefaced by \ to be interpreted as special characters, you can use raw strings by adding an r before the first quote:

print('C:\drive\name')    # here \n means newline!!
print(r'C:\drive\name')   # note the r before the quote

Strings can be concatenated with the + operator, and repeated with *:

2 * 'ma' + 'mia'

Strings can be indexed, with the first character having index 0. There is no separate character type; a character is simply a string of size one:

word = 'Python'
word[0]           # P, character in position 0
word[5]           # n, character in position 5

Indices may also be negative numbers, to start counting from the right:

word[-1]     # n, last character
word[-2]     # o, second-last character
word[-6]

Note that since -0 is the same as 0, negative indices start from -1.

In addition to indexing, slicing is also supported. While indexing is used to obtain individual characters, slicing allows you to obtain substring:

word[0:2]    # Py, characters from position 0 (included) to 2 (excluded)
word[2:5]    # tho, characters from position 2 (included) to 5 (excluded)

Note how the start is always included, and the end always excluded. This makes sure that s[:i] + s[i:] is always equal to s. Slice indices have useful defaults; an omitted first index defaults to zero, an omitted second index defaults to the size of the string being sliced.

word[:2]     # Py, character from the beginning to position 2 (excluded)
word[4:]     # on, characters from position 4 (included) to the end
word[-2:]    # on, characters from the second-last (included) to the end

Attempting to use an index that is too large will result in an error.

The built-in function len() returns the length of a string:

s = 'supercalifragilisticexpialidocious'
len(s)                                      # 34

 

Lists

Like strings, lists provide sequential storage through an index offset and access to single or consecutive elements through slices. Strings consist only of characters and are immutable (cannot change individual elements), while lists are flexible container objects that hold an arbitrary number of Python objects. Creating lists are simple.

The objects that you can place in a list can include standard types and objects as well as user-defined ones. Lists can contain different types of objects and are more flexible than an array of C structs arrays, because arrays are restricted to containing objects of a single type. Lists can be populated, empty, sorted, and reversed. Lists can be grown and shrunk. They can be taken apart and put together with other lists. Individual or multiple items can be inserted, updated, or removed at will.

squares = [1, 4, 9, 16, 25]
squares

Like strings (and all other built-in sequence types), lists can be indexed and sliced.

squares[0]     # 1, indexing returns the item
squares[-1]    # 25

All slice operations return a new list containing the requested elements. This means that the following slice returns a shallow copy of the list:

squares[-3:]    # [9, 16, 25] slicing returns a new list

Lists also support operations like concatenation.

squares + [36, 49, 64, 81, 100]    # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Unlike strings, lists are a mutable type, i.e. it is possible to change their content.

cubes = [1, 8, 27, 65, 125]    # something's wrong here
cubes[3] = 64                  # replace the wrong value

You can also add new items at the end of the list, by using the append().

cubes.append(216)    # add the cube of 6
cubes                # [1, 8, 27, 64, 125, 216]

It is possible to nest lists (create lists containing other lists).

a = ['a', 'b', 'c']
n = [1, 2, 3]
x = [a, n]
x  # [['a', 'b', 'c'], [1, 2, 3]]
x[0]       # ['a', 'b', 'c']
x[0][1]    # 'b'