IHE Python course, 2017

Tuples, lists and sets

T.N.Olsthoorn, Feb 2017


In [3]:
from pprint import pprint
import numpy as np

Tuples, lists, sets, dicts, strings and numpy arrays are the hard core of the objects just to handle data in phython. In this notebook we learn to handle tuples, lists and sets as basic tools for every day python. Next we'll do strings as immutable sequences of characters and then dicts storage devices in which we can reach values by keys. We'll show various practical ways to use them and their methods.

Lists, sets and dicts are often generated and filtered with comprehensions, we'll handle these powerfull tools in a separate notebook.

Tuples, immutable lists

Tuples are recognized by comma-separted items within paranthesis ( ) :


In [60]:
myTuple = ('This', 'is', 'our', 'tuple', 'number', 1)
print("This tuple contains {} itmes.".format(len(myTuple)))
print("Here you see that the object is a tuple: {}".format(type(myTuple)))
print("If you ask if this is a tuple, this is the answer:", isinstance(myTuple, tuple))


This tuple contains 6 itmes.
Here you see that the object is a tuple: <class 'tuple'>
If you ask if this is a tuple, this is the answer: True

In [89]:
'duck', 'goat', 'dog'  # this is also a tuple, parenthesis are not needed


Out[89]:
('duck', 'goat', 'dog')

In [95]:
print( type( ('duck')) )
('duck')  # this is not a tuple, it's a single item between paranthesis


<class 'str'>
Out[95]:
'duck'

In [96]:
print( type( ('duck',) ) )
('duck',)   # to make python recognize a single item as a tuple, put a comma behind it


<class 'tuple'>
Out[96]:
('duck',)

In [97]:
'duck',  # parenthesis are not needed, but the comma is to make it a tuple


Out[97]:
('duck',)

In [98]:
12, # this hold true for numbers as well as for any objects


Out[98]:
(12,)

Tuples are hany for multiple assignments:


In [104]:
a, b, c, d = 12, ['a', 'duck'], np.sin, ['quack', 2]

print("a = ", a)
print("b = ", b)
print("c = ", c)
print("d = ", d)


a =  12
b =  ['a', 'duck']
c =  <ufunc 'sin'>
d =  ['quack', 2]

Famous Python way of reversing values of parameters:


In [105]:
c, a, d, b = a, b, c, d

print("a = ", a)
print("b = ", b)
print("c = ", c)
print("d = ", d)


a =  ['a', 'duck']
b =  ['quack', 2]
c =  12
d =  <ufunc 'sin'>

Tuples like lists are sequences of aribitrary itmes:


In [4]:
myTuple = (12, 'a duck', np.sin, {'cat': 'Spooky', 'dog' : 'Barky', 'horse' : 'Duky'}, {'a', 'b', 'a', 'c', 'b', 'b'})

In [5]:
myTuple


Out[5]:
(12,
 'a duck',
 <ufunc 'sin'>,
 {'cat': 'Spooky', 'dog': 'Barky', 'horse': 'Duky'},
 {'a', 'b', 'c'})

You an iterate over tuples, lists and sets (and dicts and strings and possible other sequences):


In [7]:
for k in myTuple:
    print(type(k))


<class 'int'>
<class 'str'>
<class 'numpy.ufunc'>
<class 'dict'>
<class 'set'>

In [9]:
12 and np.sin in myTuple


Out[9]:
True

In [ ]:
And get values by indexing:

In [11]:
myTuple[3]


Out[11]:
{'cat': 'Spooky', 'dog': 'Barky', 'horse': 'Duky'}

In [15]:
myTuple[1:3]


Out[15]:
('a duck', <ufunc 'sin'>)

But you cannot change a tuple because it's immutable.


In [16]:
myTuple[0] = 14


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-16-962e33ce90cf> in <module>()
----> 1 myTuple[0] = 14

TypeError: 'tuple' object does not support item assignment

The methods that are associated with tuple can be seen by typing tuple then a dot and then tapping the tab key. There are only two, count(item) and index(item).


In [22]:
myTuple.count(np.sin) # returns the number of occurences of item


Out[22]:
1

In [23]:
myTuple.index(np.sin) # returns the index (location) of itme in tuple


Out[23]:
2

In [24]:
dir(tuple) # gives all methods, both "private" and public


Out[24]:
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__getnewargs__',
 '__gt__',
 '__hash__',
 '__init__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__rmul__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'count',
 'index']

Lists


In [ ]:
Lists are like tuples sequences, but the are mutable.

Lists are recognized by a series of comma-separted items within square brackets [ ]

In [62]:
myList = ['This', 'is', 'our', 'list', 'number', 1]
print("This list contains {} itmes.".format(len(myList)))
print("Here you see that the object is a list: {}".format(type(myList)))
print("If you ask if this is a list, this is the answer:", isinstance(myList, list))


This list contains 6 itmes.
Here you see that the object is a list: <class 'list'>
If you ask if this is a list, this is the answer: True

Lists like tuples are sequences of aribitrary itmes:


In [63]:
myList = [12, 'a duck', np.sin, {'cat': 'Spooky', 'dog' : 'Barky', 'horse' : 'Duky'}, {'a', 'b', 'a', 'c', 'b', 'b'}]

In [64]:
myList


Out[64]:
[12,
 'a duck',
 <ufunc 'sin'>,
 {'cat': 'Spooky', 'dog': 'Barky', 'horse': 'Duky'},
 {'a', 'b', 'c'}]

Till here there's no difference between tuples and lists. But contratry to tuples, list are mutable. You can see this from the methods that are associated with lists:

Let's use a list comprehension to get all public methods associated with lists:


In [66]:
[p for p in dir(myList) if not p.startswith('_')]


Out[66]:
['append',
 'clear',
 'copy',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']

Instead of only two (count() and index()) there are now 11. The other 9 methods can change the contents of the list. Let's use the append to append itmes to an initally empty list to get the same list as before:


In [73]:
publicListMethods = []  # empty list, you could also use = list()
for p in dir(myList):
    if not p.startswith('_'):
        publicListMethods.append(p)
publicListMethods


Out[73]:
['append',
 'clear',
 'copy',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']

Let's pop out the 'copy' using pop():


In [74]:
c = publicListMethods.pop(2)
print(c)
publicListMethods


copy
Out[74]:
['append',
 'clear',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']

Item copy was popped out and assigned to c; is now missing from list publicListMethods.

We can insert it again at (before) any position using insert:


In [75]:
publicListMethods.insert(4, 'copy')
print(publicListMethods)


['append', 'clear', 'count', 'extend', 'copy', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

In [80]:
publicListMethods.sort(reverse=True)  # inplace sort
print(publicListMethods)


['sort', 'reverse', 'remove', 'pop', 'insert', 'index', 'extend', 'count', 'copy', 'clear', 'append']

In [82]:
publicListMethods.reverse()  # inplace reverse
print(publicListMethods)


['append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

In [84]:
sorted(publicListMethods)  # sorts, not in place, it makes a copy, returns a new list


Out[84]:
['append',
 'clear',
 'copy',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']

In [87]:
help(list.sort)


Help on method_descriptor:

sort(...)
    L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*


In [86]:
help(sorted)


Help on built-in function sorted in module builtins:

sorted(iterable, key=None, reverse=False)
    Return a new list containing all items from the iterable in ascending order.
    
    A custom key function can be supplied to customise the sort order, and the
    reverse flag can be set to request the result in descending order.

We will often see more complex structures like list of lists and list of tuples or tuples of list or even lists of lists of lists. Hence we can build arbitrary comples structures, even in combination with sets and dicts.

But list of lists or lists of tuples or tuples of tuples or tuples of lists are very common.


In [118]:
listList = [['quack', 'duck', 'age', 2],
            ['bark', 'dog', 'age', 2],
            ['splash', 'fish', 'age', 5],
            ['tweet', 'Trump', 'age', 70]]

We can access any item with indexing and slicing:


In [124]:
listList[1]


Out[124]:
['bark', 'dog', 'age', 2]

In [125]:
listList[3:0:-1]


Out[125]:
[['tweet', 'Trump', 'age', 70],
 ['splash', 'fish', 'age', 5],
 ['bark', 'dog', 'age', 2]]

In [126]:
listList[2][2]


Out[126]:
'age'

In [127]:
listList[2][3:1:-1]


Out[127]:
[5, 'age']

In [128]:
p = listList.pop(2)
print(p)
print(listList)
listList.append(p)
print(listList)


['splash', 'fish', 'age', 5]
[['quack', 'duck', 'age', 2], ['bark', 'dog', 'age', 2], ['tweet', 'Trump', 'age', 70]]
[['quack', 'duck', 'age', 2], ['bark', 'dog', 'age', 2], ['tweet', 'Trump', 'age', 70], ['splash', 'fish', 'age', 5]]

Sets

Python has a full set of set logic.

A set is recognized by itmes within curly braces { }


In [131]:
mySet =  {'dog', 'cat', 'cat', 'horse', 'fish', 'dog', 'camel'}
yourSet = {'bird', 'cat', 'elephant', 'chimp', 'dog', 'elephant', 'zebra'}
print(mySet)
print(yourSet)


{'cat', 'fish', 'dog', 'camel', 'horse'}
{'cat', 'dog', 'elephant', 'zebra', 'bird', 'chimp'}

You see that only the unique itmes are kept. Their order if of no importance.

Which itmes are in mySet and not in yourSet ??


In [132]:
print(mySet - yourSet)


{'fish', 'camel', 'horse'}

Which itmes are in yourSet and not in mySet ??


In [135]:
print(yourSet - mySet)


{'elephant', 'zebra', 'bird', 'chimp'}

Which items are in either set?


In [137]:
print(yourSet | mySet)


{'cat', 'dog', 'camel', 'elephant', 'zebra', 'bird', 'horse', 'fish', 'chimp'}

Which items are in both sets?


In [138]:
print(yourSet & mySet)


{'cat', 'dog'}

Adding and multiplying tuples and lists

Becaus Python is an object oriented languages, in which any item is an object that carries along a set of methods that is associated with it, any method can be defined to mean what is useful for the class of objects to which it belongs.

Arithmathic addition and multiplication have not direct meaning for lists and tuples. But the + and the * can be benificially redefined for tuples and lists (and strings) to mean concatenation and multiple concatenation instead.


In [150]:
myList = ['john', 'goes', 'home']
yourList=['with', 'mary']
print(myList + yourList)
print(yourList * 6)
print( (myList + yourList) * 2)
print('John walks home'  + ' with Mary')  # addition of two strings
print('-' * 80)   # holds also for strings, multiplication of a string


['john', 'goes', 'home', 'with', 'mary']
['with', 'mary', 'with', 'mary', 'with', 'mary', 'with', 'mary', 'with', 'mary', 'with', 'mary']
['john', 'goes', 'home', 'with', 'mary', 'john', 'goes', 'home', 'with', 'mary']
John walks home with Mary
--------------------------------------------------------------------------------

In [152]:
'Today, ' + str(5) + ' boats arrived at about ' + str(12) + " o'clock."  # use str(number) to convert to string


Out[152]:
"Today, 5 boats arrived at about 12 o'clock."

In [ ]: