Lecture: Sequences and Loops¶

Today we'll talk about sequences, an abstract type that exemplified by two concrete types: str and list.
We will talk about the common properties of sequences, as well as a new execution mode: looping.

1. Motivating example: counting vowels¶

Assume we are given different words, such as "Wellesley", "Boston", "abracadbra", "osteoarthritis", and so on, and want to count the number of vowels in each word, or to count how many times a particular letter occurs in the word.

How do we do that? First, we'll need our "old friend", isVowel as a predicate that we can use in conditional statements.

Old friend: isVowel¶

In [1]:
def isVowel(char):
"""Predicate that returns true only when a letter is a vowel."""
c = char.lower()
return (c == 'a' or c == 'e' or c == 'i' or
c == 'o' or c == 'u')
In [2]:
def testIsVowel(char):
"""Helper function to test isVowel"""
print("isVowel('" + char + "')",  "=>",  isVowel(char))
In [3]:
testIsVowel('d')
testIsVowel('D')
testIsVowel('a')
testIsVowel('E')
testIsVowel('i')
testIsVowel('O')
testIsVowel('u')
testIsVowel('y')
isVowel('d') => False
isVowel('D') => False
isVowel('a') => True
isVowel('E') => True
isVowel('i') => True
isVowel('O') => True
isVowel('u') => True
isVowel('y') => False

Use indices to access elements in a string¶

We can access each character (or element) in a string word by using indices. These are integers from 0 to len(word)-1

In [4]:
word = "Boston"
word[0]
Out[4]:
'B'
In [5]:
len(word)
Out[5]:
6
In [6]:
word[1]
Out[6]:
'o'
In [7]:
word[3]
Out[7]:
't'

Question: Will the following expression work?

In [8]:
word[6]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-8-8fed510628cf> in <module>
----> 1 word[6]

IndexError: string index out of range

In [9]:
word[-1]
Out[9]:
'n'

Question: Can you access the character "s" by using a negative index? Write it below to test:

In [10]:
word[-4]
Out[10]:
's'

Sequential vs. Chained conditionals¶

How can we count the vowels in a word? We can use isVowel and the indices to test each character and keep track of vowels through a counter variable.

But, how do we write the conditionals to test for each character?

Scenario 1: A series of if statements¶

Can you predict the result?

In [11]:
word = 'Boston'
counter = 0
if isVowel(word[0]):
counter += 1
if isVowel(word[1]):
counter += 1
if isVowel(word[2]):
counter += 1
if isVowel(word[3]):
counter += 1
if isVowel(word[4]):
counter += 1
if isVowel(word[5]):
counter += 1
print(counter)
2

Scenario 2: Chained conditionals¶

Can you predict the result?

In [12]:
word = 'Boston'
counter = 0
if isVowel(word[0]):
counter += 1
elif isVowel(word[1]):
counter += 1
elif isVowel(word[2]):
counter += 1
elif isVowel(word[3]):
counter += 1
elif isVowel(word[4]):
counter += 1
elif isVowel(word[5]):
counter += 1
print(counter)
1

Try the code with another word¶

We always strive to write code that is generic, what will happen when we run it with a new string?

In [13]:
word = 'Lynn'
counter = 0
if isVowel(word[0]):
counter += 1
if isVowel(word[1]):
counter += 1
if isVowel(word[2]):
counter += 1
if isVowel(word[3]):
counter += 1
if isVowel(word[4]):
counter += 1
if isVowel(word[5]):
counter += 1
print(counter)
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-13-62d91339842c> in <module>
9 if isVowel(word[3]):
10     counter += 1
---> 11 if isVowel(word[4]):
12     counter += 1
13 if isVowel(word[5]):

IndexError: string index out of range

2. for loops¶

We can solve the problem of vowel-counting using a for loop. A loop is an execution mechanism. It repeats a series of statements for a certain number of times.

In [14]:
word = 'Boston'
for letter in word:
print('letter has the value', letter)
letter has the value B
letter has the value o
letter has the value s
letter has the value t
letter has the value o
letter has the value n
In [15]:
word = 'Boston'
counter = 0
for letter in word:
if isVowel(letter):
print(letter + ' is a vowel')
counter += 1
else:
print(letter + ' is not a vowel')
print(word + ' has ' + str(counter) + ' vowels')
B is not a vowel
o is a vowel
s is not a vowel
t is not a vowel
o is a vowel
n is not a vowel
Boston has 2 vowels

Note that this approach works for strings of any length:

In [16]:
word = 'Deerfield'
counter = 0
for letter in word:
if isVowel(letter):
print(letter + ' is a vowel')
counter += 1
else:
print(letter + ' is not a vowel')
print(word + ' has ' + str(counter) + ' vowels')
D is not a vowel
e is a vowel
e is a vowel
r is not a vowel
f is not a vowel
i is a vowel
e is a vowel
l is not a vowel
d is not a vowel
Deerfield has 4 vowels
In [17]:
word = 'Manchester-by-the-Sea'
counter = 0
for letter in word:
if isVowel(letter):
print(letter + ' is a vowel')
counter += 1
else:
print(letter + ' is not a vowel')
print(word + ' has ' + str(counter) + ' vowels')
M is not a vowel
a is a vowel
n is not a vowel
c is not a vowel
h is not a vowel
e is a vowel
s is not a vowel
t is not a vowel
e is a vowel
r is not a vowel
- is not a vowel
b is not a vowel
y is not a vowel
- is not a vowel
t is not a vowel
h is not a vowel
e is a vowel
- is not a vowel
S is not a vowel
e is a vowel
a is a vowel
Manchester-by-the-Sea has 6 vowels
In [18]:
word = 'Lynn'
counter = 0
for letter in word:
if isVowel(letter):
print(letter + ' is a vowel')
counter += 1
else:
print(letter + ' is not a vowel')
print(word + ' has ' + str(counter) + ' vowels')
L is not a vowel
y is not a vowel
n is not a vowel
n is not a vowel
Lynn has 0 vowels

Question: What will happen if we remove the conditional statement if, as shown below. Can you predict what is printed?

In [19]:
word = 'Boston'
counter = 0
for letter in word:
counter += 1
print(counter)
6

Exercise 1: countAllVowels¶

Abstract over the for loop examples from above to define a function countAllVowels that takes one argument -- a word -- and return the number of vowels in that word. Note that the print statements describing each letter are optional - we used them above as a debugging technique to understand what the for loop was doing. Feel free to include them or not, as you prefer.

In [20]:
def countAllVowels(word):
counter = 0
for letter in word:
if isVowel(letter):
counter += 1
return counter
In [21]:
def testCountAllVowels(word):
"""Helper function to test countAllVowels"""
print("countAllVowels('" + word + "')",  "=>",  countAllVowels(word))
In [22]:
testCountAllVowels('Lynn')
testCountAllVowels('Boston')
testCountAllVowels('Wellesley')
testCountAllVowels('Deerfield')
testCountAllVowels('Middleborough')
testCountAllVowels('Manchester-by-the-Sea')
testCountAllVowels('pneumonoultramicroscopicsilicovolcanoconiosis')
countAllVowels('Lynn') => 0
countAllVowels('Boston') => 2
countAllVowels('Wellesley') => 3
countAllVowels('Deerfield') => 4
countAllVowels('Middleborough') => 5
countAllVowels('Manchester-by-the-Sea') => 6
countAllVowels('pneumonoultramicroscopicsilicovolcanoconiosis') => 20

Exercise 2: countChar¶

Define a function countChar that takes two arguments -- a character and a word -- and returns the number of times that character appears in the word.

In [23]:
def countChar(char, word):
counter = 0
for letter in word:
if letter == char:
counter += 1
return counter
In [24]:
def testCountChar(char, word):
"""Helper function to test countChar"""
print("countAllVowels('" + char + "', '" + word + "')",  "=>",  countChar(char, word))
In [25]:
testCountChar('i', 'Mississippi')
testCountChar('p', 'Mississippi')
testCountChar('M', 'Mississippi')
testCountChar('m', 'Mississippi')
testCountChar('-', 'Manchester-by-the-Sea')
testCountChar('t', 'To be or not to be')
testCountChar(' ', 'To be or not to be')
countAllVowels('i', 'Mississippi') => 4
countAllVowels('p', 'Mississippi') => 2
countAllVowels('M', 'Mississippi') => 1
countAllVowels('m', 'Mississippi') => 0
countAllVowels('-', 'Manchester-by-the-Sea') => 3
countAllVowels('t', 'To be or not to be') => 2
countAllVowels(' ', 'To be or not to be') => 5

3. New type: list¶

Lists are another type in Python just like strings or ints. Lists are an ordered sequence of values. Lists are declared with square brackets and items are separated by commas. Lists are an example of a data structure. Lists are meant to store data where the order of the data matters.

In [26]:
[42, 3, -7]
Out[26]:
[42, 3, -7]

Lists can have the same type or different types of values.

In [27]:
[True, 3.4, "hello"]
Out[27]:
[True, 3.4, 'hello']

Similar to other types that we have seen: integer, float and string, there is a built-in function with the name of the type that generates values of that types by converting from a type to another. The function list below converts strings to a list of string characters.

In [28]:
list("Wendy Wellesley")
Out[28]:
['W', 'e', 'n', 'd', 'y', ' ', 'W', 'e', 'l', 'l', 'e', 's', 'l', 'e', 'y']

Question: Will it work the same way with integers?

In [29]:
list(100)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-29-f4a5da02c9e6> in <module>
----> 1 list(100)

TypeError: 'int' object is not iterable

Question: What if you convert the number into a string first, and then try to turn it into a list. Will that work?

In [30]:
list(str(3.14159265))
Out[30]:
['3', '.', '1', '4', '1', '5', '9', '2', '6', '5']

4. for loops over other sequences¶

In addition to iterating over the letters of strings, we can iterate over other types of sequences, such as ranges and lists.

In [31]:
#Let's check how many divisors a number has.
number = 8
divisors = 0
for candidate in [1,2,3,4,5,6,7,8]:
if number % candidate == 0:
divisors = divisors + 1
print(str(number) + ' has ' + str(divisors) + ' divisors')

8 has 4 divisors
In [32]:
# And again...
number = 11
divisors = 0
for candidate in [1,2,3,4,5,6,7,8,9,10,11]:
if number % candidate == 0:
divisors = divisors + 1
print(str(number) + ' has ' + str(divisors) + ' divisors')

11 has 2 divisors

Notice that we have to hardcode the list of numbers. This means we can't use this code on any number. We'll learn about a new tool that lets us generalize our divisor counting now.

Creating sequences of numbers with the built-in function range¶

The first argument of range starts the sequence, and all numbers up to (but not including) the second argument are generated.

In [33]:
range(0, 10)
Out[33]:
range(0, 10)

The range function returns an object that holds the sequence. To see the contents of range's sequence, pass it into the built-in list function that will return a list of numbers. We will talk more about the list function in subsequent classes.

In [34]:
list(range(0, 10))
Out[34]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

We'll get an empty list when the two arguments are the same, or the first is greater than the second:

In [35]:
a = range(3, 3)
b = range(3, 1)
print(list(a))
print(list(b))
[]
[]

Omiting the first argument means we want to start at 0 by default

In [36]:
list(range(8))
Out[36]:
[0, 1, 2, 3, 4, 5, 6, 7]

Using range with three arguments¶

range takes a third argument, the value of the step between two generated values. If this value is missing, by default step is 1.

In [37]:
# The even numbers
list(range(0, 10, 2))
Out[37]:
[0, 2, 4, 6, 8]
In [38]:
# Stepping by 10
list(range(3, 70, 10))
Out[38]:
[3, 13, 23, 33, 43, 53, 63]

The step can be negative. When the step is negative, the start needs to be greater than the end of the range.

In [39]:
list(range(10, 0, -1))
Out[39]:
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

Your turn: Write the range to produce all nonnegative integers up to and including 50 that are divisible by 5:

In [40]:
nums = range(0,51,5)
list(nums)
Out[40]:
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]

We can iterate over this sequence just like any other sequence!

In [41]:
for i in range(11):     # Starts at 0, goes up to n-1
print(i)
0
1
2
3
4
5
6
7
8
9
10

If we want the range of numbers from 1 up to and including number, here's one way we can do that:

In [42]:
number = 11
for i in range(number):
print(i + 1)                # Add 1 to the number before using it
1
2
3
4
5
6
7
8
9
10
11

Remember that we can also explicitly set both the start and end values for range:

In [43]:
number = 13
for i in range(1, number + 1):   # Ask range to give us the right numbers directly
print(i)
1
2
3
4
5
6
7
8
9
10
11
12
13

Now we can generalize our divisor counting!

In [44]:
def countDivisors(number):
divisors = 0
for candidate in range(1, number + 1):
if number % candidate == 0:
divisors = divisors + 1
return divisors
In [45]:
countDivisors(8)
Out[45]:
4
In [46]:
countDivisors(11)
Out[46]:
2

You can also use range to repeat some code multiple times even if you don't use the iteration variable.

In [47]:
for _ in range(10):                                    # The variable name _ is just a normal variable name,
print('Say this tongue twister ten times fast!')   # but some programmers use it as a convention to indicate to
# a reader of the code that syntax requires a variable name
# but they don't plan to use the value stored in that variable.
Say this tongue twister ten times fast!
Say this tongue twister ten times fast!
Say this tongue twister ten times fast!
Say this tongue twister ten times fast!
Say this tongue twister ten times fast!
Say this tongue twister ten times fast!
Say this tongue twister ten times fast!
Say this tongue twister ten times fast!
Say this tongue twister ten times fast!
Say this tongue twister ten times fast!

Write a function doublesUpTo which takes a number x and prints out each of the integers up to and including x doubled. For example, doublesUpTo(4) should print out

0
2
4
6
8
In [48]:
def doublesUpTo(x):
for i in range(x+1):
print(i * 2)

doublesUpTo(4)
0
2
4
6
8

5. Using indices in loops¶

Sometimes your loop needs both the values in a sequence as well as their indices. For example, let's imagine that you're running an amusement park. When people want to get on a ride, they put their initials on a waitlist. Then, you display the waitlist on a screen so folks can know how close to the front of the line they are. So for example, if some prominent American figures wanted to ride, the screen might show something like:

#0: BHO
#1: MLRO
#2: MAO
#3: SO
#4: AOC
#5: NPP
#6: RBG

Our first attempt might look like this:

In [49]:
waitlist = ['BHO', 'MLRO', 'MAO', 'SO', 'AOC', 'NPP', 'RBG']
for name in waitlist:
print(name)
BHO
MLRO
MAO
SO
AOC
NPP
RBG

But this doesn't print the indices, which are an important piece of information that we wanted to display. In this case, we will often use range to generate indices, like so:

In [50]:
waitlist = ['BHO', 'MLRO', 'MAO', 'SO', 'AOC', 'NPP', 'RBG']
for spot in range(len(waitlist)):           # Range generates the indices
name = waitlist[spot]                   # Use indexing to get the value
print('#' + str(spot) + ': ' + name)    # Perform a calculation using both value and index.
#0: BHO
#1: MLRO
#2: MAO
#3: SO
#4: AOC
#5: NPP
#6: RBG
In [51]:
# Once Barack gets off the list and is on the rollercoaster, you can see that everyone else has moved up
waitlist = ['MLRO', 'MAO', 'SO', 'AOC', 'NPP', 'RBG']
for spot in range(len(waitlist)):
name = waitlist[spot]
print('#' + str(spot) + ': ' + name)
#0: MLRO
#1: MAO
#2: SO
#3: AOC
#4: NPP
#5: RBG

6. Drills with range and for loops¶

Use range to make x hold the same list as goal in each cell. The first one has been done for you as an example:

In [52]:
goal = [0,1,2,3,4]

x = list(range(5))
In [53]:
assert goal == x
print('Success!')
Success!
In [54]:
goal = [0,1,2,3,4,5,6,7]

x = list(range(8))
In [55]:
assert goal == x
print('Success!')
Success!
In [56]:
goal = [1,2,3,4]

x = list(range(1, 5))
In [57]:
assert goal == x
print('Success!')
Success!
In [58]:
goal = [0,2,4,6]

x = list(range(0, 8, 2))
In [59]:
assert goal == x
print('Success!')
Success!
In [60]:
goal = [5, 8, 11, 14]

x = list(range(5, 15, 3))
In [61]:
assert goal == x
print('Success!')
Success!
In [62]:
goal = [100, 200]

x = list(range(100, 300, 100))
In [63]:
assert goal == x
print('Success!')
Success!

Write a function that uses a for loop to print out all the letters in the string s, one per line

In [64]:
s = 'abcdef'

# Expected output:
'''
a
b
c
d
e
f
'''

for let in s:
print(let)
a
b
c
d
e
f

Write a function that uses a for loop to print out all the numbers in the list nums

In [65]:
nums = [1, 6, 2, 9, 10]

# Expected output:
'''
1
6
2
9
10
'''

for num in nums:
print(num)
1
6
2
9
10

Write a function that uses a for loop to print out each of the numbers in the list nums divided by 2

In [66]:
nums = [1, 6, 2, 9, 10]

# Expected output:
'''
0.5
3.0
1.0
4.5
5.0
'''

for num in nums:
print(num/2)
0.5
3.0
1.0
4.5
5.0

Write a function countEvens that returns the number of even numbers in a list

In [67]:
def countEvens(nums):
evens = 0
for n in nums:
if n % 2 == 0:
evens += 1
return evens
In [68]:
assert countEvens([1,2,3,4,5,6]) == 3
assert countEvens([1,1,1,1,1,1]) == 0
assert countEvens([2]) == 1
print('Correct!')
Correct!

Write a function countOdds that returns the number of odd numbers in a list

In [69]:
def countOdds(nums):
odds = 0
for n in nums:
if n % 2 == 1:
odds += 1
return odds
In [70]:
assert countOdds([1,2,3,4,5,6]) == 3
assert countOdds([1,1,1,1,1,1]) == 6
assert countOdds([2]) == 0
print('Correct!')
Correct!

Write a function countDoubleDigits that returns the number of double digit numbers in a list

In [71]:
def countDoubleDigits(nums):
dds = 0
for n in nums:
if n > 9 and n < 100:
dds += 1
return dds
In [72]:
assert countDoubleDigits([1,2,3,4,5,6]) == 0
assert countDoubleDigits([10,112,112,12,71,1]) == 3
assert countDoubleDigits([15]) == 1
print('Correct!')
Correct!

Write a function countNegatives that returns the number of negative numbers in a list

In [73]:
def countNegatives(nums):
negs = 0
for n in nums:
if n < 0:
negs += 1
return negs
In [74]:
assert countNegatives([1,2,-3,-4,-5,-6]) == 4
assert countNegatives([1,1,1,1,1,1]) == 0
assert countNegatives([-2]) == 1
print('Correct!')
Correct!

Write a function tongueTwister that takes a string and prints the string 5 times

In [75]:
def tongueTwister(phrase):
for _ in range(5):
print(phrase)
In [76]:
#Expected output:
'''
She sells sea-shells by the sea shore
She sells sea-shells by the sea shore
She sells sea-shells by the sea shore
She sells sea-shells by the sea shore
She sells sea-shells by the sea shore
'''

tongueTwister('She sells sea-shells by the sea shore')
She sells sea-shells by the sea shore
She sells sea-shells by the sea shore
She sells sea-shells by the sea shore
She sells sea-shells by the sea shore
She sells sea-shells by the sea shore

Write a for loop that iterates over the given string, printing out each index and letter in the string

In [79]:
s = 'koala'

#Expected output
'''
0 k
1 o
2 a
3 l
4 a
'''

for index in range(len(s)):
print(index, s[index])
0 k
1 o
2 a
3 l
4 a

Write a for loop that iterates over the given list, printing out the product of each element and its index.

In [78]:
nums = [4, 5, 9]
# Expected output
'''
0 4
1 5
2 9
'''

for i in range(len(nums)):
val = nums[i]
print(i, val)
0 4
1 5
2 9

Write a for loop that iterates over the given list, printing out the product of each value with its index

In [80]:
nums = [4, 5, 9]
# Expected output
'''
0
5
18
'''

for i in range(len(nums)):
val = nums[i]
print(i * val)
0
5
18

Write a for loop that iterates over the given list, printing out each word. If the word's index in the list is greater than 2, add an exclamation mark to the end of the word

In [81]:
nums = ['I', 'welcome', 'you', 'to', 'my', 'delightful', 'garden']
# Expected output
'''
I
welcome
you
to!
my!
delightful!
garden!
'''

for i in range(len(nums)):
val = nums[i]
if i > 2:
print(val + '!')
else:
print(val)
I
welcome
you
to!
my!
delightful!
garden!

7. Operations with sequences¶

A sequence, is a series of items for which the relative order to one-another matters. In Python, a sequence is the parent class for strings, lists, and ranges. This way, all of these classes will share their behavior (in terms of what operations can be applied to them), but they also will have differences, which we will discuss in the coming lectures.

In [82]:
word = "Boston"
digits = [1, 2, 3, 4]
digRange = range(1, 5)
In [83]:
word
Out[83]:
'Boston'
In [84]:
digits
Out[84]:
[1, 2, 3, 4]
In [85]:
digRange
Out[85]:
range(1, 5)

Indexing: We access an element by using the [ ] operator and a number that is the index of the element in the sequence.

In [86]:
word[2]
Out[86]:
's'
In [87]:
digits[2]
Out[87]:
3
In [88]:
digRange[2]
Out[88]:
3

Finding length: Because sequences consist of zero or more items, we can use len to find how many items they contain.

In [89]:
len(word)
Out[89]:
6
In [90]:
len(digits)
Out[90]:
4
In [91]:
len(digRange)
Out[91]:
4

Concatenation: Sequences can be concatenated by using the operators '+' or '*'

In [92]:
word + " Globe"
Out[92]:
'Boston Globe'
In [93]:
digits + [4]
Out[93]:
[1, 2, 3, 4, 4]

Note that concatenation is not supported for range objects.

In [94]:
digRange + range(4)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-94-e35c5d6c1483> in <module>
----> 1 digRange + range(4)

TypeError: unsupported operand type(s) for +: 'range' and 'range'
In [95]:
word * 3
Out[95]:
'BostonBostonBoston'
In [96]:
digits * 2
Out[96]:
[1, 2, 3, 4, 1, 2, 3, 4]
In [97]:
digRange * 2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-97-d7d50eb36fcd> in <module>
----> 1 digRange * 2

TypeError: unsupported operand type(s) for *: 'range' and 'int'

The membership operator in: this operator returns True when an item is part of the sequence, and False otherwise

In [98]:
't' in word
Out[98]:
True
In [99]:
'a' in word
Out[99]:
False
In [100]:
'ton' in word
Out[100]:
True
In [101]:
'bos' in word
Out[101]:
False
In [102]:
1 in digits
Out[102]:
True
In [103]:
5 in digits
Out[103]:
False
In [104]:
1 in digRange
Out[104]:
True
In [105]:
5 in digRange
Out[105]:
False
In [106]:
def isVowel2(char):
"""Use in for a simpler definition of isVowel"""
return char.lower() in 'aeiou'
In [107]:
def testIsVowel2(char):
"""Helper function to test isVowel"""
print("isVowel2('" + char + "')",  "=>",  isVowel2(char))
In [108]:
testIsVowel2('d')
testIsVowel2('D')
testIsVowel2('a')
testIsVowel2('E')
testIsVowel2('i')
testIsVowel2('O')
testIsVowel2('u')
testIsVowel2('y')
isVowel2('d') => False
isVowel2('D') => False
isVowel2('a') => True
isVowel2('E') => True
isVowel2('i') => True
isVowel2('O') => True
isVowel2('u') => True
isVowel2('y') => False

Slicing: this operation uses two indices (a start and a stop) to create a subsequence of items between the two indices.

In [109]:
word[1:4]
Out[109]:
'ost'
In [110]:
digits[1:4]
Out[110]:
[2, 3, 4]
In [111]:
digRange[1:4]
Out[111]:
range(2, 5)

If the first index is omitted, the start index is by default 0.

In [112]:
word[:3]
Out[112]:
'Bos'
In [113]:
digits[:3]
Out[113]:
[1, 2, 3]
In [114]:
digRange[:3]
Out[114]:
range(1, 4)

If the stop index is greater than the length of the sequence, Python doesn't return an error, it returns the sequence until the end.

In [115]:
word[3:10]
Out[115]:
'ton'

But, we can omit the stop index entirely and get the rest of the subsequence:

In [116]:
word[3:]
Out[116]:
'ton'

We can use a third parameter, step, with the slicing operator. Step works just like step for range, skipping a certain number of items.

In [117]:
word[0:6:2]
Out[117]:
'Bso'
In [118]:
digits[0:5:2]
Out[118]:
[1, 3]
In [119]:
digRange[0:5:2]
Out[119]:
range(1, 5, 2)

We can omit the stop argument as before, and Python automatically will look until the end of the sequence.

In [120]:
digits[0::2]
Out[120]:
[1, 3]

Reversing through slicing: because Python allows negative indexing (see slide 15), by using step -1, we can reverse a sequence.

In [121]:
word[::-1]
Out[121]:
'notsoB'
In [122]:
digits[::-1]
Out[122]:
[4, 3, 2, 1]
In [123]:
digRange[::-1]
Out[123]:
range(4, 0, -1)

From strings to lists

We can create a list from a string using the list function.

In [124]:
list(word)
Out[124]:
['B', 'o', 's', 't', 'o', 'n']

We can also produce a list by splitting a string at spaces. This is commonly use to split a sentence into a list of words.

In [125]:
phrase = "New England's weather is unpredictable."
phrase.split()
Out[125]:
['New', "England's", 'weather', 'is', 'unpredictable.']

When the split method doesn't take arguments, it splits by default at the white space. If needed, you can split at some other character.

In [126]:
message = "I woke up. The sun rose too. The sky was serene."
message.split('.')
Out[126]:
['I woke up', ' The sun rose too', ' The sky was serene', '']

Notice how the character "." was removed and the string was split exactly where the "." was.