Advanced Datatypes#

These notes follow the official python tutorial pretty closely: http://docs.python.org/3/tutorial/

Lists#

Lists group together data. These are roughly equivalent to the C++ vector class. A list can grow as the data grows.

Unlike C++ vectors, lists can hold data of all different types – they don’t need to be homogeneos (although, in practice, this is rarely useful).

A list is defined using square brackets:

a = [1, 2.0, "my list", 4]
print(a)
[1, 2.0, 'my list', 4]

We can index a list to get a single element – remember that python starts counting at 0:

print(a[2])
my list

Like with strings, mathematical operators are defined on lists:

print(a*2)
[1, 2.0, 'my list', 4, 1, 2.0, 'my list', 4]

The len() function returns the length of a list

print(len(a))
4

Unlike strings, lists are mutable – you can change elements in a list easily

a[1] = -2.0
a
[1, -2.0, 'my list', 4]

Note that lists can even contain other lists:

a[1] = ["other list", 3]
a
[1, ['other list', 3], 'my list', 4]

Just like everything else in python, a list is an object that is the instance of a class. Classes have methods (functions) that know how to operate on an object of that class.

There are lots of methods that work on lists. Two of the most useful are append, to add to the end of a list, and pop, to remove the last element:

a.append(6)
a
[1, ['other list', 3], 'my list', 4, 6]
a.pop()
6
a
[1, ['other list', 3], 'my list', 4]

Quick Exercise:

An operation we’ll see a lot is to begin with an empty list and add elements to it. An empty list is created as:


 a = []
 
  • Create an empty list

  • Append the integers 1 through 5 to it.

  • Now pop them out of the list one by one.

copying lists#

copying may seem a little counterintuitive at first. The best way to think about this is that your list lives in memory somewhere and when you do

a = [1, 2, 3, 4]

then the variable a is set to point to that location in memory, so it refers to the list.

If we then do

b = a

then b will also point to that same location in memory – the exact same list object.

Since these are both pointing to the same location in memory, if we change the list through a, the change is reflected in b as well:

a = [1, 2, 3, 4]
b = a  # both a and b refer to the same list object in memory
print(a)
a[0] = "changed"
print(b)
[1, 2, 3, 4]
['changed', 2, 3, 4]

if you want to create a new object in memory that is a copy of another, then you can either index the list, using : to get all the elements, or use the list() function:

c = list(a)   # you can also do c = a[:], which basically slices the entire list
a[1] = "two"
print(a)
print(c)
['changed', 'two', 3, 4]
['changed', 2, 3, 4]

There are lots of other methods that work on lists (remember, ask for help)

my_list = [10, -1, 5, 24, 2, 9]
my_list.sort()
print(my_list)
[-1, 2, 5, 9, 10, 24]
print(my_list.count(-1))
my_list
1
[-1, 2, 5, 9, 10, 24]
help(a.insert)
Help on built-in function insert:

insert(index, object, /) method of builtins.list instance
    Insert object before index.
a.insert(3, "my inserted element")
a
['changed', 'two', 3, 'my inserted element', 4]

joining two lists is simple. Like with strings, the + operator concatenates:

b = [1, 2, 3]
c = [4, 5, 6]
d = b + c
print(d)
[1, 2, 3, 4, 5, 6]

Dictionaries#

A dictionary stores data as a key:value pair. Unlike a list where you have a particular order, the keys in a dictionary allow you to access information anywhere easily:

my_dict = {"key1":1, "key2":2, "key3":3}
print(my_dict["key1"])
1

you can add a new key:pair easily, and it can be of any type

my_dict["newkey"] = "new"
print(my_dict)
{'key1': 1, 'key2': 2, 'key3': 3, 'newkey': 'new'}

You can also easily get the list of keys that are defined in a dictionary

keys = list(my_dict.keys())
print(keys)
['key1', 'key2', 'key3', 'newkey']

and check easily whether a key exists in the dictionary using the in operator

print("key1" in keys)
print("invalidKey" in keys)
True
False

Quick Exercise:

Create a dictionary where the keys are the string names of the numbers zero to five and the values are their numeric representation (0, 1, … , 5)

List Comprehensions#

list comprehensions provide a compact way to initialize lists. Some examples from the tutorial

squares = [x**2 for x in range(10)]
squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

here we use another python type, the tuple, to combine numbers from two lists into a pair

[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Quick Exercise:

Use a list comprehension to create a new list from squares containing only the even numbers. It might be helpful to use the modulus operator, %

Tuples#

tuples are immutable – they cannot be changed, but they are useful for organizing data in some situations. We use () to indicate a tuple:

a = (1, 2, 3, 4)
print(a)
(1, 2, 3, 4)

We can unpack a tuple:

w, x, y, z = a
print(w)
1
print(w, x, y, z)
1 2 3 4

Since a tuple is immutable, we cannot change an element:

a[0] = 2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[32], line 1
----> 1 a[0] = 2

TypeError: 'tuple' object does not support item assignment

But we can turn it into a list, and then we can change it