Lists, Tuples, sorting, Reading from files

List & Tuple

Lists and Tuples are at a first look very alike. The are created the same way, the are both indexed can be sliced in the same way etc.
The most prominent difference is that lists are mutable, tuples are imutable. Meaning that lists can change, you can add and remove elements over time. Tuples stay the same always.

Semantic difference

The most important difference come when we look at the semantic difference. Which points at what we should use each one for.
Tuples are heterogeneous data structures (i.e., their entries have different meanings), while lists are homogeneous sequences (i.e., the entries are most often of the same type). Tuples have structure, lists have order.

On lists you can often perform the same action on all its elements (i.e., in a loop run the same functionallity on all its elements)

li = [1, 2, 3, 4]
for i in l1:
    print(i**2)

, where elements of a tuple normally not would behave in the same way/have the same type.

card = ('♠', 10)
for i in card:
    print(i**2)  # this would not work

Examples og things you would put in a list:

  • Playing Cards (making the list a Deck of cards)

  • Objects of a certain type (Persons or Students e.i)

  • Domainnames (http:www.kea.dk)

Example of things you would put in a tuple:

  • A playing card (color and face) (’♠’, 10) (’♦’, 2) (’♥’, 6) (’♣’, 5)

  • Atributes of a Student (name, age, class)

  • Domain name with a connected ssh key (‘azureuser@22.165.213.31’, ‘<private key path>’ )

Tuples are records, lists are a big box of the simalar stuff, a collection of the same type of objects.

In a tuple the order has meaning. In the card example above we would know that the color always are the first element, and the face the second.

In a list it is not important where a specific object are. It could be in the beginning or the end. It is not important where, but only important that it is of the same type.

Definition

You can define a list like this:

[2]:
li = ['Hans', 'Alice', 'Bob']

Often the same Type, but not a requirement.

And a Tuple the same way:

[3]:
tu = ('♠', 10)

Refer

List and tuples are indexed and thus can be referenced like this:

[4]:
li[0]
[4]:
'Hans'
[5]:
tu[0]
[5]:
'♠'

Changing values

You can change the values of a list by assigning new values to a key

[7]:
li[2] = 'Tine'
li
[7]:
['Hans', 'Alice', 'Tine']

Since Tuples are imutable you can not change its values, and trying to will result in an error

[9]:
tu[1] = '4'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[9], line 1
----> 1 tu[1] = '4'

TypeError: 'tuple' object does not support item assignment

Ordered

Lists and tuples are ordered. They are human ordered, meaning in the order in which you specify the elements when you define it, or in lists case when you append or remove elements from the list.

Build in functions the same syntax for everything

Python is deliberately consistent.
The build in functions can be seen as an API that works on all objects where it makes sence.
[5]:
len(li), len(tu)
[5]:
(3, 2)
[6]:
type(li), type(tu)
[6]:
(list, tuple)
[7]:
help(li)
Help on list object:

class list(object)
 |  list(iterable=(), /)
 |
 |  Built-in mutable sequence.
 |
 |  If no argument is given, the constructor creates a new empty list.
 |  The argument must be an iterable if specified.
 |
 |  Methods defined here:
 |
 |  __add__(self, value, /)
 |      Return self+value.
 |
 |  __contains__(self, key, /)
 |      Return key in self.
 |
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |
 |  __eq__(self, value, /)
 |      Return self==value.
 |
 |  __ge__(self, value, /)
 |      Return self>=value.
 |
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |
 |  __gt__(self, value, /)
 |      Return self>value.
 |
 |  __iadd__(self, value, /)
 |      Implement self+=value.
 |
 |  __imul__(self, value, /)
 |      Implement self*=value.
 |
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |
 |  __iter__(self, /)
 |      Implement iter(self).
 |
 |  __le__(self, value, /)
 |      Return self<=value.
 |
 |  __len__(self, /)
 |      Return len(self).
 |
 |  __lt__(self, value, /)
 |      Return self<value.
 |
 |  __mul__(self, value, /)
 |      Return self*value.
 |
 |  __ne__(self, value, /)
 |      Return self!=value.
 |
 |  __repr__(self, /)
 |      Return repr(self).
 |
 |  __reversed__(self, /)
 |      Return a reverse iterator over the list.
 |
 |  __rmul__(self, value, /)
 |      Return value*self.
 |
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |
 |  __sizeof__(self, /)
 |      Return the size of the list in memory, in bytes.
 |
 |  append(self, object, /)
 |      Append object to the end of the list.
 |
 |  clear(self, /)
 |      Remove all items from list.
 |
 |  copy(self, /)
 |      Return a shallow copy of the list.
 |
 |  count(self, value, /)
 |      Return number of occurrences of value.
 |
 |  extend(self, iterable, /)
 |      Extend list by appending elements from the iterable.
 |
 |  index(self, value, start=0, stop=9223372036854775807, /)
 |      Return first index of value.
 |
 |      Raises ValueError if the value is not present.
 |
 |  insert(self, index, object, /)
 |      Insert object before index.
 |
 |  pop(self, index=-1, /)
 |      Remove and return item at index (default last).
 |
 |      Raises IndexError if list is empty or index is out of range.
 |
 |  remove(self, value, /)
 |      Remove first occurrence of value.
 |
 |      Raises ValueError if the value is not present.
 |
 |  reverse(self, /)
 |      Reverse *IN PLACE*.
 |
 |  sort(self, /, *, key=None, reverse=False)
 |      Sort the list in ascending order and return None.
 |
 |      The sort is in-place (i.e. the list itself is modified) and stable (i.e. the
 |      order of two equal elements is maintained).
 |
 |      If a key function is given, apply it once to each list item and sort them,
 |      ascending or descending, according to their function values.
 |
 |      The reverse flag can be set to sort in descending order.
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  __class_getitem__(...) from builtins.type
 |      See PEP 585
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __hash__ = None

[8]:
id(li), id(tu)
[8]:
(140607034921920, 140607111934656)
[9]:
all(li), all(tu)
[9]:
(True, True)

Concatenate

[10]:
[2,3,4,5] + [1, 2, 3, 4]
[10]:
[2, 3, 4, 5, 1, 2, 3, 4]

Multiply

[11]:
[1, 2, 3, 4] * 4
[11]:
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]

Reference

Variables in python are “by reference”.
An object exists in memory, and we then put on yellow sticky notes (variable names).
(You can add more sticky notes to the object if you want to).
[12]:
a = ['Hans', 'Alice', 'Bob']
b = a
a[0] = 'Torben' # adding to a also changes b
a
[12]:
['Torben', 'Alice', 'Bob']
[13]:
b
[13]:
['Torben', 'Alice', 'Bob']

So ‘b’ does not create a copy but points at the same object in memory. There is only one ['Torben', 'Alice', 'Bob']

[14]:
a is b
[14]:
True

Slicing

[15]:
a[1:4]
[15]:
['Alice', 'Bob']
[16]:
a[-1]
[16]:
'Bob'
[17]:
a[::-1]
[17]:
['Bob', 'Alice', 'Torben']

Loop

For each loop

[18]:
for i in li:
    print(i)
Hans
Alice
Bob

Same thing with Strings

[19]:
s = 'Hello'
for i in s:
    print(i)
H
e
l
l
o

Check if a value is in a list/tuple or not

[20]:
a
[20]:
['Torben', 'Alice', 'Bob']
[21]:
'Jens' in a
[21]:
False
[22]:
'Bob' in a
[22]:
True
[23]:
2 not in a
[23]:
True

You can do the same on strings

[24]:
's' in s
[24]:
False
[25]:
'a' not in s
[25]:
True

Methods

Methods are called like this:

object.method()

Methods are specific for the object it belongs to, and therefor also differs between Lists and Tuples

[26]:
a.append(333)
a
[26]:
['Torben', 'Alice', 'Bob', 333]
[27]:
a.pop()
[27]:
333
[28]:
a.pop(2)
[28]:
'Bob'

Removes and returns the value

Sorting

sorted()

[38]:
a = [3, 6, 1, 2, 9, 3, 5]
sorted(a)
[38]:
[1, 2, 3, 3, 5, 6, 9]
[39]:
a
[39]:
[3, 6, 1, 2, 9, 3, 5]

Returns a sorted list. Does not change the original.

Parameters

[40]:
# sorted(e, reverse= True/False, key=func)
[41]:
sorted(a, reverse=True)
[41]:
[9, 6, 5, 3, 3, 2, 1]
[42]:
a = ['Hans', 'Alice', 'Bob', 'Esmarada', 'Hans Jørgen', 'Arne']
sorted(a, key=len)
[42]:
['Bob', 'Hans', 'Arne', 'Alice', 'Esmarada', 'Hans Jørgen']

image0

Key functions

Sort by name with 5 or more letters.

[43]:
def five_or_more(x):
    if len(x) >= 5:
        return False
    return True
[44]:
sorted(a, key=five_or_more)
[44]:
['Alice', 'Esmarada', 'Hans Jørgen', 'Hans', 'Bob', 'Arne']

.sort()

.sort() is a method in the list object.
Avoid using this, instead use sorted()
Reason:
* sorted() can be used on all ‘iterable objects’, .sort() only works on lists.
* sorted() does not change the original list, .sort() does.

String example

[45]:
s.sort()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-45-474c8408a842> in <module>
----> 1 s.sort()

AttributeError: 'str' object has no attribute 'sort'
[46]:
sorted(s, reverse=True)
[46]:
['o', 'l', 'l', 'e', 'H']

Files

Read from files

[49]:
f = open('testfiles/bohr.txt')
f.read()
[49]:
'An expert is a person who has made all the mistakes that can be made in a very narrow field.\nPrediction is very difficult, especially about the future.\nThose who are not shocked when they first come across quantum theory cannot possibly have understood it.\n'
[50]:
f = open('testfiles/bohr.txt')
f.readline()
[50]:
'An expert is a person who has made all the mistakes that can be made in a very narrow field.\n'
[51]:
f = open('testfiles/bohr.txt')
f.readlines()
[51]:
['An expert is a person who has made all the mistakes that can be made in a very narrow field.\n',
 'Prediction is very difficult, especially about the future.\n',
 'Those who are not shocked when they first come across quantum theory cannot possibly have understood it.\n']

Write to files

[52]:
f = open('testfiles/test.txt', 'w')
f.write('Hello world')
[52]:
11
[53]:
f = open('testfiles/test.txt')
f.read()
[53]:
'Hello world'

Tuples

Tuples are another datastructure of ordered objects.

‘Ordered collection of objects’.

Tuples are written with () instead of [].
Tuples are’imutable’ -> they can not be changed

Definition:

[54]:
t = (1, 2, 3, 4)

Also not necessarily of the same type

Refer

[55]:
t[2]
[55]:
3

Build in functions

[56]:
len(a)
[56]:
6

Concatenate

[78]:
t + ('a', 'b')
[78]:
(1, 2, 3, 4, 'a', 'b')
[79]:
t
[79]:
(1, 2, 3, 4)

Multiply

[57]:
(1, 2, 3, 4) * 2
[57]:
(1, 2, 3, 4, 1, 2, 3, 4)

Slicing

[58]:
t[:3]
[58]:
(1, 2, 3)

Loop

For each loop

[59]:
for i in t:
    print(i, end=',')
1,2,3,4,