Python Containers

Published May 11, 2020, 9:42 a.m.

In our last tutorial, we dealt with a singular variables. Often you will want to use multiple variables in structured sequences.  Structured sequences of variables require containers-- something to bookend the sequence. This tutorial will cover three kinds of containers for sequences:  Lists, tuples and Dictionaries. 

Takeaways:

  • List containers use square brackets and are zero-indexed;  Lists are mutable. 
    • A_List = [data1, data2, data3...]
  • Tuple containers use parentheses and are zero-indexed but are immutable. 
    • A_tuple = (data1, data2, data3...)
  • Dictionary containers use curly braces and have user-defined keys for indexes; Dictionaries are mutable. 
    • A_dict = {key1:data1, key2:data2,...}

Lists and tuples are very similar and I will discuss them first. 

The most common variable sequence is the list.  A list in python appears between sqaure brackets. 

list1 = ['a', 'b', 'c', 'd', 'e']

>>> list1 = ['a', 'b', 'c', 'd', 'e']
>>> list1
['a', 'b', 'c', 'd', 'e']
>>>

Another common sequence type is a  tuple (pronounced tuh-pl) and it appears between parentheses:

tup1 = (1,2,3,4)

>>> tup1 = (1,2,3,4)
>>> tup1
(1, 2, 3, 4)

The type function that we used in the last tutortial works on variable types as well.

>>> type(list1)
<class 'list'>
>>> type(tup1)
<class 'tuple'>
>>>

Both sequences are 'zero-indexed' meaning that you can get an element from the list or tuple using an index that starts from 0.

To return the index from both lists and tuples, you use square brackets.

>>> tup1[0]
1
>>> list1[0]
'a'

This is because the use of parentheses after text is reserved for functions and definitions and such (as we'll see later).

The code above shows that the index-0 element of tup1 is 1 and the index-0 element of list1 is 'a' (which is correct).  What happens if we ask for an index that isn't there?  For instance there are only 4 elements in tup1.  The indexes are 0, 1, 2, 3 corresponding to values 1,2,3,4. If I ask for index (5) I will get an error.

>>> tup1[5]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Error: index out of range
>>>

This is our first forced error of the tutorial series.  I want to highlight that errors are inevitable.  One of the awesome things about python is that you can work in this interactive environment and see what throws an error and what does not.  (But I digress).

If you know the data element but you want python to give you the index, the list and tuple classes afford you that.

>>> list1.index('a')
0
>>> tup1.index(1)
0
>>>

Here, I asked python to return the index of the element 'a' from list 1 and the index of the number 1 from tup1.  Both indicies were 0.

In python a list is a class of objects that are mutable (or changeable). I can add new elements to list1 with an attribute called 'append'.

>>> list1.append('f')
>>> list1
['a', 'b', 'c', 'd', 'e', 'f']

If I try something similar on the tuple...

>>> tup1.append(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'append'
>>>

I cannot append to tup1 because that class of objects is 'immutable' (i.e. not changeable).

In a simiilar way, I can delete an element from list1:

>>> list1.remove('c')
>>> list1
['a', 'b', 'd', 'e', 'f']
>>>

but not from tup1:

>>> tup1.remove(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'remove'
>>>

The final variable sequenece that we will discuss in this tutorial is the dictionary.  In python a dictionary is defined between curly braces.

dict1 = {}

A dictionary is an 'associative array' similar to lists and tuples, but unlike lists and tuples, dictionaries are not zero-indexed.  In fact, the key feature of a dictionary is that the index is created by the user.  For example:

dict1 = { 'name':'Bob', 'age':99, 'height': 72, 'country':'The United States'} is a dictionary where the value 'Bob' has the index 'name':

>>> dict1 = { 'name':'Bob', 'age':99, 'height': 72, 'country':'The United States'}
>>> dict1['name']
'Bob'

One can imediately see how useful this kind of indexing might be. This is one of the features of python that I think programmers really like about it.  Python was built around a desire for a programming language that emphaized code-readability.

Note that the syntax for these index:elements for dictionaries is refered to as key:value. Keys may be floats, strings or integers. Let us create a new dictionary with some interesting key types.

>>> dict2 = {}
>>> dict2[3.14159]="Pi"
>>> dict2["Pi"]= 3.1415926
>>> dict2[3] = "Almost Pi"
>>>

The above demonstrates another way to create keys in a dictionary.  Like a list, dictionaries are mutable, but unlike a list, the dictionary does not have an 'append' attribute.  In the example above, the keys are inside the brackets and the values are on the other side of the equal sign.  Keys can be retrieved by a method within the dictionary class:

>>> dict2.keys()
dict_keys([3.14159, 'Pi', 3])
>>>

Finally, the values inside lists, tuples and dictionaries can be any mix of the data types AND/OR the variable types.  For instance:

>>> tup1 = (1,2,3)
>>> tup2 = (4,5,6)
>>> tup3 = (tup1, tup2, list1, dict2)
>>> list1.append(tup3)
>>> list1
['a', 'b', 'd', 'e', 'f', ((1, 2, 3), (4, 5, 6), [...], {3.14159: 'Pi', 'Pi': 3.1415926, 3: 'Almost Pi'})]

Now that is just the craziest thing right there.  I didn't even think that it would work.  I have re-defined tup1 as (1,2,3).  I defined tup2 as (4,5,6).  I defined tup3 as (tup1, tup2, list1, dict2).  Then I appended tup3 to list1.  When I look at list1, I see my list from before (with the value 'c' removed.) and added on to the list is tup3.  I can check the last value of a list like so:

>>> list1[-1]
((1, 2, 3), (4, 5, 6), ['a', 'b', 'd', 'e', 'f', (...)], {3.14159: 'Pi', 'Pi': 3.1415926, 3: 'Almost Pi'})
>>>

where the index '-1' is a pythonic way of indexing from the last value of a list.  Notice the elipses (...).  This is how python handles an instance of self-referenceing.

I googled it and found an answer in stackoverflow: https://stackoverflow.com/questions/50955371/self-referential-list-in-python

Normally, it is considered cleaner to stick to one data-type or variable type in a container.  Next we will start looking at loops and logic in python.

 

skip_nextLoops and Logic
  • Download Python!

  • Python Interactive Session

  • Python Data Types

  • Python Containers
    (currently viewing)
  • Loops and Logic