lists¶
A list is an object that can hold other objects
Lists are represented with
[]
Lists can be made with the list constructor
Lists can hold any object
Lists can be changed after creation by performing an operation, this means they are mutable
Lists can be looped over
test_making_a_list¶
red: make it fail¶
I make a file called test_lists.py
in the tests
folder with the following code
import unittest
class TestLists(unittest.TestCase):
def test_making_a_list(self):
self.assertEqual(list(0, 1, 2, 3), None)
the terminal shows TypeError
TypeError: list expected at most 1 argument, got 4
green: make it pass¶
I add the error to the list of Exceptions encountered
# Exceptions Encountered # AssertionError # TypeError
Looking at the error I see that the list constructor expects one argument but four are given in the test, so I am not following the signature for making lists
a constructor is a function that is used to make an instance of a class
I read python’s documentation for lists and see that the list constructor takes an iterable as input
An iterable is an object I can go over its items one by one in a loop - tuples, lists, sets and dictionaries are iterable
I make the values provided to the list constructor a tuple by placing them in parentheses
def test_making_a_list(self): self.assertEqual(list((0, 1, 2, 3)), [])
and get AssertionError in the terminal
AssertionError: [0, 1, 2, 3] != None
When I make the right side match the values on the left from the terminal
def test_making_a_list(self): self.assertEqual(list((0, 1, 2, 3)), [0, 1, 2, 3])
the test passes
refactor: make it better¶
I can make a list with the list constructor but the passing test also shows I can make a list with
[]
which uses less characters. I add a test for itdef test_making_a_list_w_square_brackets(self): self.assertEqual([0, 1, 2, 3], list((0, 1, 2, 4)))
the terminal shows AssertionError for the last value
AssertionError: Lists differ: [0, 1, 2, 3] != [0, 1, 2, 4]
and I change the value in the test to make it pass
def test_making_a_list_w_square_brackets(self): self.assertEqual([0, 1, 2, 3], list((0, 1, 2, 3)))
test_adding_an_item_to_a_list¶
red: make it fail¶
I add a test for adding items to an existing list with the append method
def test_adding_an_item_to_a_list(self):
a_list = [0, 1, 2, 3]
self.assertEqual(a_list, [0, 1, 2, 3])
a_list.append(4)
self.assertEqual(a_list, [0, 1, 2, 3])
a_list = [0, 1, 2, 3]
makes a list of 4 items and calls ita_list
the first
self.assertEqual(a_list, [0, 1, 2, 3])
checks thata_list
has the four itemsself.assertEqual(a_list, [0, 1, 2, 3])
checks whata_list
has after append is called
the terminal shows AssertionError because the values in a_list
change after a_list.append(4)
is called
AssertionError: Lists differ: [0, 1, 2, 3, 4] != [0, 1, 2, 3]
green: make it pass¶
I make the values in the test match the values in the terminal
def test_adding_an_item_to_a_list(self):
a_list = [0, 1, 2, 3]
self.assertEqual(a_list, [0, 1, 2, 3])
a_list.append(4)
self.assertEqual(a_list, [0, 1, 2, 3, 4])
and it shows passing tests.
I started with a list that had 4 things, added something using the append method, then confirmed what I added is now part of the list
test_removing_an_item_from_a_list¶
red: make it fail¶
Since I know how to add an item to a list I want to add a test for taking away an item from a list using the remove method
def test_removing_an_item_from_a_list(self):
a_list = [0, 1, 2, 3]
self.assertEqual(a_list, [0, 1, 2, 3])
a_list.remove(2)
self.assertEqual(a_list, [0, 1, 2, 3])
the terminal shows AssertionError because 2
is no longer in a_list
after a_list.remove(2)
is called
AssertionError: Lists differ: [0, 1, 3] != [0, 1, 2, 3]
green: make it pass¶
I make the values match the values in the terminal and the test passes
def test_removing_an_item_from_a_list(self):
a_list = [0, 1, 2, 3]
self.assertEqual(a_list, [0, 1, 2, 3])
a_list.remove(2)
self.assertEqual(a_list, [0, 1, 3])
refactor: make it better¶
What happens when there is more than one of the same item in a list? How does Python decide which of them to remove when I call .remove(item)
on a list?
I add a failing test to find out
def test_removing_an_item_from_a_list_when_multiple_exist(self): a_list = [0, 2, 1, 2, 3, 2] self.assertEqual(a_list, [0, 2, 1, 2, 3, 2]) a_list.remove(2) self.assertEqual(a_list, [0, 2, 1, 2, 3, 2])
and get AssertionError in the terminal
AssertionError: Lists differ: [0, 1, 2, 3, 2] != [0, 2, 1, 2, 3, 2]
then I make the values on the right match the values from the terminal to make it pass
def test_remove_an_item_from_a_list_when_multiple_exist(self): a_list = [0, 2, 1, 2, 3, 2] self.assertEqual(a_list, [0, 2, 1, 2, 3, 2]) a_list.remove(2) self.assertEqual(a_list, [0, 1, 2, 3, 2])
From the test I see that the remove method takes away the first item when there is more than one of the same item in a list
test_removing_the_last_item_from_a_list¶
red: make it fail¶
I add a test for taking away the last item from a list
def test_removing_the_last_item_from_a_list(self):
a_list = [0, 1, 2, 3]
self.assertEqual(a_list, [0, 1, 2, 3])
last_item = a_list.pop()
self.assertEqual(last_item, 0)
self.assertEqual(a_list, [0, 1, 2, 3])
last_item = a_list.pop()
calls the pop method ofa_list
and useslast_item
as a name to represent the value that is returnedself.assertEqual(last_item, 0)
checks thatlast_item
is equal to0
self.assertEqual(a_list, [0, 1, 2, 3])
checks the values that remain ina_list
after calling pop
the terminal shows AssertionError for the test that checks the value of the popped item called last_item
> self.assertEqual(last_item, 0)
E AssertionError: 3 != 0
green: make it pass¶
I make the value in the test match the actual value popped
self.assertEqual(last_item, 3)
and the terminal shows AssertionError for the values of
a_list
after the last item is poppedAssertionError: Lists differ: [0, 1, 2] != [0, 1, 2, 3]
I change the values in the test that checks the values of
a_list
after calling popdef test_removing_the_last_item_from_a_list(self): a_list = [0, 1, 2, 3] self.assertEqual(a_list, [0, 1, 2, 3]) last_item = a_list.pop() self.assertEqual(last_item, 3) self.assertEqual(a_list, [0, 1, 2])
and get passing tests
test_getting_items_from_a_list¶
To view an item in a list I can provide the position as an index in []
to the list. Python uses zero-based indexing which means the positions of items starts at 0. I can also view items from the right side of the list by using negative numbers
red: make it fail¶
I add a failing test for indexing a list
def test_getting_items_from_a_list(self):
a_list = ['first', 'second', 'third', 'fourth']
self.assertEqual(a_list, ['first', 'second', 'third', 'fourth'])
self.assertEqual(a_list[0], '')
self.assertEqual(a_list[2], '')
self.assertEqual(a_list[1], '')
self.assertEqual(a_list[3], '')
self.assertEqual(a_list[-1], '')
self.assertEqual(a_list[-3], '')
self.assertEqual(a_list[-2], '')
self.assertEqual(a_list[-4], '')
the terminal shows AssertionError
AssertionError: 'first' != ''
- first
green: make it pass¶
I change the value in the test to make the failing line pass
def test_getting_items_from_a_list(self): a_list = ['first', 'second', 'third', 'fourth'] self.assertEqual(a_list, ['first', 'second', 'third', 'fourth']) self.assertEqual(a_list[0], 'first') self.assertEqual(a_list[2], '') self.assertEqual(a_list[1], '') self.assertEqual(a_list[3], '') self.assertEqual(a_list[-1], '') self.assertEqual(a_list[-3], '') self.assertEqual(a_list[-2], '') self.assertEqual(a_list[-4], '')
the terminal shows AssertionError for the next test
AssertionError: 'third' != ''
I make the value match what is in the terminal
def test_getting_items_from_a_list(self): a_list = ['first', 'second', 'third', 'fourth'] self.assertEqual(a_list, ['first', 'second', 'third', 'fourth']) self.assertEqual(a_list[0], 'first') self.assertEqual(a_list[2], 'third') self.assertEqual(a_list[1], '') self.assertEqual(a_list[3], '') self.assertEqual(a_list[-1], '') self.assertEqual(a_list[-3], '') self.assertEqual(a_list[-2], '') self.assertEqual(a_list[-4], '')
and get a failure for the next test
AssertionError: 'second' != ''
I change each failing line until all the tests pass
def test_getting_items_from_a_list(self): a_list = ['first', 'second', 'third', 'fourth'] self.assertEqual(a_list, ['first', 'second', 'third', 'fourth']) self.assertEqual(a_list[0], 'first') self.assertEqual(a_list[2], 'third') self.assertEqual(a_list[1], 'second') self.assertEqual(a_list[3], 'fourth') self.assertEqual(a_list[-1], 'fourth') self.assertEqual(a_list[-3], 'second') self.assertEqual(a_list[-2], 'third') self.assertEqual(a_list[-4], 'first')
test_index_error¶
IndexError is raised when I try to get an item from a list but use a number that is greater than the number of items in the list.
red: make it fail¶
I add a failing test to show this
def test_index_error(self):
a_list = ['first', 'second', 'third', 'fourth']
a_list[5]
the terminal shows IndexError
> a_list[5]
E IndexError: list index out of range
green: make it pass¶
I add IndexError to the list of Exceptions encountered
# Exceptions Encountered # AssertionError # TypeError # IndexError
then add a
self.assertRaises
to confirm that theIndexError
gets raised and the test passesdef test_index_error(self): a_list = ['a', 'b', 'c', 'd'] with self.assertRaises(IndexError): a_list[5]
unittest.TestCase.assertRaises takes an Exception as input and confirms that it is raised. You can read more about
self.assertRaises
in how to test that an Exception is raised
refactor: make it better¶
I add one more line to test indexing with a negative number that is greater than the length of the list
def test_index_error(self): a_list = ['a', 'b', 'c', 'd'] with self.assertRaises(IndexError): a_list[5] a_list[-5]
the terminal shows IndexError
When I indent the line under the self.assertRaises context, the test passes
with self.assertRaises(IndexError): a_list[5] a_list[-5]
test_list_attributes_and_methods¶
The chapter on classes shows how to view the attributes and methods of an object by using the dir function. Let us try it for lists
red: make it fail¶
I add a failing test using the dir function
def test_list_attributes_and_methods(self):
self.assertEqual(
dir(list),
[]
)
the terminal shows AssertionError
green: make it pass¶
The terminal also shows a recommendation on how to see the difference between
dir(list)
and[]
Diff is 748 characters long. Set self.maxDiff to None to see it
maxDiff is an attribute of the unittest.TestCase class that sets the maximum amount of characters to show in the comparison between the 2 objects in the terminal. When it is set to None there is no limit to the number of characters
I add
self.maxDiff
to the testdef test_list_attributes_and_methods(self): self.maxDiff = None self.assertEqual( dir(list), [] )
and the terminal shows a long list of items
I copy and paste the items from the terminal and remove the extra characters
Note
Your results may vary based on your version of Python
def test_list_attributes_and_methods(self): self.maxDiff = None self.assertEqual( dir(list), [ '__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort' ] )
and the terminal shows passing tests
refactor: make it better¶
There are more methods listed than what I have reviewed. Based on their names, I can make a guess at what they do, and I know some from the tests above
append - adds an item to the list
clear - does this clear the items in the list?
copy - does this make a copy of the list?
count - does this count the number of items in the list?
extend - does this extend the list?
index
insert - does this place an item in the list? what’s the difference between this and append?
pop - takes away the last item in the list
remove - takes away the first occurrence of a given item in the list
reverse - does this reverse the list?
sort - does this sort the items in the list?
You can add tests for these methods to find out what they do or read more about lists
review¶
Lists are represented with
[]
Lists can be made with the list constructor
Lists can hold any object
Lists can be changed after creation by performing an operation, this means they are mutable
Lists can be looped over
I ran the following tests to show things I can do with lists in Python
and ran into the following Exceptions
Would you like to test list comprehensions?