We've seen numeric types, like int, float and complex. Another kind/classification of type is a sequence. A sequence:
Sequences support operations like:
A string is an ordered sequence of characters. It is a sequence type. It supports:
"blubbins?"[0] #index, first element -> "b"
"blubbins?"[-1] #index, last element -> "?"
"blubbins?"[1:4] #slices -> "lub"
"blubbins?"[4:] #slices -> "bins?"
"what the " + "blubbins?" # concatenates -> "what the blubbins?"
"blubbins?" * 2 # repeats -> "blubbins?blubbins?"
A list is another sequence type.
# a list of ints
stuff = [1, "one", 2, "two"]
Constructing a list using a list literal looks like this:
["some", "stuff", "between", "brackets"]
You can pass lists directly to the built-in print function. It will output the list as if it were a string literal:
>>> a = [2, 3, 5, 7]
>>> print(a)
[2, 3, 5, 7]
You can also use str() or string interpolation to create a string representation of a list:
>>> a = [2, 3, 5, 7]
>>> print("Some numbers in a list: %s" % a)
Some numbers in a list: [2, 3, 5, 7]
Because a list is just another sequence type many of the built-in operators and functions that work with strings behave similarly with lists.
What will the following code output? →
import math
land_of_ooo = ["jake", "finn", "princess bubblegum"]
a = -1
print(land_of_ooo[0])
print(land_of_ooo[2])
print(land_of_ooo[a])
print(land_of_ooo[int(math.sqrt(1))])
jake
princess bubblegum
princess bubblegum
finn
What will the following code output? →
import math
land_of_ooo = ["jake", "finn", "princess bubblegum"]
a = -1
print(land_of_ooo[3])
print(land_of_ooo[1.0])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not float
Using the list below, How would you retrieve "homer"… once using a positive index, and another time using a negative index? →
simpsons = ["marge", "homer", "lisa"]
simpsons[1]
simpsons[-2]
Just like iterating over a sequence of characters…
What will the following for loop print out? →
some_boolean_values = [True, True, False]
for b in some_boolean_values:
print(b)
True
True
False
Slicing also works on lists. What will the folloing code output? →
colors = ["red", "green", "blue", "taupe"]
print(colors[0:2])
print(colors[2:])
print(colors[:3])
print(colors[0:100])
['red', 'green']
['blue', 'taupe']
['red', 'green', 'blue']
['red', 'green', 'blue', 'taupe']
Again… like slicing strings.
Lists are compared lexicographically using comparison of corresponding elements; to be equal each element must compare equal and the two sequences must be of the same type and have the same length.
Equal or not equal? →
print([1, 2, 3] == [1, 2, 3])
print(['a', 'b', 'c'] == [1, 2, 3])
print(['a', 'b', 'c'] != [1, 2, 3])
True
False
True
If not equal, the sequences are ordered the same as their first differing elements.
Equal or not equal? →
['a', 'b', 1, 2] > ['b', 'b', 1, 2]
[5, 2] < [5, 2, 1]
['x', 'y', 'z'] < ['x', 'a', 'z']
False
True
False
Multiplication and addition of lists are similar to the same operations on strings. What will the following code output? →
toppings = ["mushrooms", "peppers", "onions"]
numbers = [2, 3, 5, 7]
print(toppings + numbers)
print(toppings * 2)
print(numbers * 2)
["mushrooms", "peppers", "onions", 2, 3, 5, 7]
["mushrooms", "peppers", "onions", "mushrooms", "peppers", "onions"]
[2, 3, 5, 7, 2, 3, 5, 7]
You can still use the built-in function, len, on lists. What do you think the following code will output? →
a = ["foo", "bar", "baz"]
b = []
c = ["foo", "bar", "baz", [1, 2, 3]]
print(len(a))
print(len(b))
print(len(c))
3
0
4
Unlike strings, however, lists are mutable. That means that you can reassign a value at an index! What will the following code print out? →
>>> a = [3, 4, 5]
>>> a[0] = "surprise"
>>> print(a)
['surprise', 4, 5]
Lists are objects, and they have a slew of methods that you can call on them. However, because lists are mutable, many methods actually change the list in place! Let's see how this differs from strings:
>>> s = 'hello'
>>> s.upper()
'HELLO'
>>> print(s)
hello
>>> numbers = [5, 3, 4]
>>> numbers.sort()
>>> print(numbers)
[3, 4, 5]
So…. why does this matter?
li = [1, 2, 3]
def last_to_first(items):
""" makes last element in list first, shifts every other element up one """
if len(items) <= 1:
return items
else:
return [items[-1]] + items[0:-1]
assert [1] == last_to_first([1]), 'test that one element returns same list'
assert [] == last_to_first([]), 'test that empty list returns empty list'
assert [4, 1, 2, 3] == last_to_first([1, 2, 3, 4]), 'test that all elements shifted by one'
def last_to_first(items):
""" makes last element in list first, shifts every other element up one """
new_items = items[:]
if len(items) > 1:
new_items.insert(0, new_items.pop())
return new_items
assert [1] == last_to_first([1]), 'test that one element returns same list'
assert [] == last_to_first([]), 'test that empty list returns empty list'
assert [4, 1, 2, 3] == last_to_first([1, 2, 3, 4]), 'test that all elements shifted by one'
Implement a function called more_characters_than: →
print(more_characters_than(["zebra", "cow", "tiger"], 4))
['zebra', 'tiger']
(btw, there's already a filter function in Python)
def more_characters_than(words, min):
new_list = []
for word in words:
if len(word) > min:
new_list.append(word)
return new_list
assert ['zebra', 'tiger'] == more_characters_than(["zebra", "cow", "tiger"], 4), "only strings with more than 4 characters"
assert [] == more_characters_than([], 4), "an empty list returns an empty list"
def average(numbers):
sum = 0
for n in numbers:
sum += n
return sum / len(numbers)
assert 9 == average([2, 3, 4]), "takes a list of integers and returns the average value"
Using the built-in sum:
def average(numbers):
return sum(numbers) / len(numbers)
Testing for membership within a list is similar to testing for a character in a string. Use the in operator. It returns True if the operand on the left is an element in the list on right. What does the following code print out? →
print('c' in ['a','b', 'c'])
print('c' not in ['a', 'b', 'c'])
breakfast = ["oatmeal", "tofu scramble", "ramen"]
if "ramen" in breakfast:
print("ramen for breakfast")
else:
print("wise decision")
True
False
ramen for breakfast
You can delete list items using del statement:
What does the following code print out? →
vegetables = ["broccoli", "cauliflower", "brownie sundae", "carrot"]
del vegetables[2]
print(vegetables)
['broccoli', 'cauliflower', 'carrot']
There are two useful string methods that are often used with lists:
comics = "ranma,maison ikkoku,scott pilgrim"
awesome_comics_list = comics.split(",")
print(awesome_comics_list)
print(" and ".join(awesome_comics_list))
['ranma', 'maison ikkoku', 'scott pilgrim']
ranma and maison ikkoku and scott pilgrim
If I have the following list, how do I put together each element with an exclamation point and space between each element? How do I turn the resulting string back to a list? →
hello = ["Bill", "Phil", "Gil", "Jill"]
names = "! ".join(hello)
print(names)
print(names.split("! "))
The random module offers some methods that can be used on lists:
Let's try using a couple of these methods →
import random
numbers = [1, 2, 3, 4, 5, 6, 7]
print(random.choice(numbers))
random.shuffle(numbers)
print(numbers)