# 3 Structures

Python features several different basic integrated structures. In this section we will discuss some of them: lists, tuplets, sets and dictionaries.

## 3.1 Lists

One of the most flexible structures in Python is the list. It is a grouping of values. The creation of a list is done by writing the values by separating them with a comma and surrounding them by square brackets ([ and ]).

x = ["Pascaline", "Gauthier", "Xuan", "Jimmy"]
print(x)
## ['Pascaline', 'Gauthier', 'Xuan', 'Jimmy']

The content of a list is not necessarily text:

y = [1, 2, 3, 4, 5]
print(y)
## [1, 2, 3, 4, 5]

It is even possible to include elements of different types in a list:

z = ["Piketty", "Thomas", 1971]
print(z)
## ['Piketty', 'Thomas', 1971]

A list can contain another list:

tweets = ["aaa", "bbb"]
followers = ["Anne", "Bob", "Irma", "John"]
compte = [tweets, followers]
print(compte)
## [['aaa', 'bbb'], ['Anne', 'Bob', 'Irma', 'John']]

### 3.1.1 Extraction of the Elements

Access to the elements is made thanks to its indexation (be careful, the index of the first element is 0):

print(x) # The first element of x
## Pascaline
print(x) # The second element of x
## Gauthier

Access to an element can also be done by starting from the end, by putting the minus sign (-) in front of the index:

print(x[-1]) # The last element of x
## Jimmy
print(x[-2]) # The penultimate element of x
## Xuan

Splitting a list so as to obtain a subset of the list is done with the colon (:):

print(x[1:2]) # The first and second elements of x
## ['Gauthier']
print(x[2:]) # From the second element (not included) to the end of x
## ['Xuan', 'Jimmy']
print(x[:-2]) # From the first to the penultimate (not included)
## ['Pascaline', 'Gauthier']
The extraction from a list using the brackets returns a list.

When extracting items from the list using the brackets, it is possible to add a third argument, the step :

print(x[::2]) # Every other element
## ['Pascaline', 'Xuan']

Access to nested lists is done by using the brackets several times:

tweets = ["aaa", "bbb"]
followers = ["Anne", "Bob", "Irma", "John"]
conuts = [tweets, followers]
res = conuts # The 4th item of the 2nd item on the list counts

The number of elements in a list is obtained with the function len() :

print(len(conuts))
## 2
print(len(conuts))
## 4

### 3.1.2 Modification

Lists are mutable, i.e., their content can be modified once the object has been created.

#### 3.1.2.1 Replacement

To modify an element in a list, the indexes can be used:

x = [1, 3, 5, 6, 9]
x = 7 # Replacing the 4th element
print(x)
## [1, 3, 5, 7, 9]

To add items to a list, the method append() can be used:

x.append(11) # Add value 11 at the end of the list
print(x)
## [1, 3, 5, 7, 9, 11]

It is also possible to use the extend() method, to concatenate lists:

y = [13, 15]
x.extend(y)
print(x)
## [1, 3, 5, 7, 9, 11, 13, 15]

#### 3.1.2.3 Deleting Elements

To removing an item from a list, the method remove() can be used:

x.remove(3) # Remove the fourth element
print(x)
## [1, 5, 7, 9, 11, 13, 15]

The del command can also be used:

x = [1, 3, 5, 6, 9]
del x # Remove the fourth element
print(x)
## [1, 3, 5, 9]

#### 3.1.2.4 Multiple assignments

Several values can be modified at the same time:

x = [1, 3, 5, 6, 10]
x[3:5] = [7, 9] # Replaces 4th and 5th values
print(x)
## [1, 3, 5, 7, 9]

The modification can increase the size of the list:

x = [1, 2, 3, 4, 5]
x[2:3] = ['a', 'b', 'c', 'd'] # Replaces the 3rd value
print(x)
## [1, 2, 'a', 'b', 'c', 'd', 4, 5]

Several values can be deleted at the same time:

x = [1, 2, 3, 4, 5]
x[3:5] = [] # Removes the 4th and 5th values
print(x)
## [1, 2, 3]

### 3.1.3 Verifying if a Value is Present

By using the operator in, it is possible to test the belonging of an object to a list:

x = [1, 2, 3, 4, 5]
print(1 in x)
## True

### 3.1.4 Copy of List

Be careful, copying a list is not trivial in Python. Let’s take an example.

x = [1, 2, 3]
y = x

Let’s modify the first element of y, and look at the content of y and x:

y = 0
print(y)
## [0, 2, 3]
print(x)
## [0, 2, 3]

As can be seen, using the equal sign simply created a reference and not a copy.

To copy a list, there are several ways to do so. Among them, the use of the list() function:

x = [1, 2, 3]
y = list(x)
y = 0
print("x : ", x)
## x :  [1, 2, 3]
print("y : ", y)
## y :  [0, 2, 3]

It can be noted that when a splitting is done, a new object is created, not a reference:

x = [1, 2, 3, 4]
y = x[:2]
y = 0
print("x : ", x)
## x :  [1, 2, 3, 4]
print("y : ", y)
## y :  [0, 2]

### 3.1.5 Sorting

To sort the objects in the list (without creating a new one), Python offers the method sort() :

x = [2, 1, 4, 3]
x.sort()
print(x)
## [1, 2, 3, 4]

It also works with text values, sorting in alphabetical order:

x = ["c", "b", "a", "a"]
x.sort()
print(x)
## ['a', 'a', 'b', 'c']

It is possible to provide the sort() method with arguments. Among these arguments, there is one, key, which provides a function for sorting. This function must return a value for each object in the list, on which the sorting will be performed. For example, with the len() function, which, when applied to text, returns the number of characters:

x = ["aa", "a", "aaaaa", "aa"]
x.sort(key=len)
print(x)
## ['a', 'aa', 'aa', 'aaaaa']

## 3.2 Tuples

The tuples are sequences of Python objects.

To create a tuple, one lists the values, separated by commas:

x = 1, 4, 9, 16, 25
print(x)
## (1, 4, 9, 16, 25)

It should be noted that tuplets are identified by a series of values, surrounded in two brackets.

### 3.2.1 Extraction of the Elements

The elements of a tuple are extracted in the same way as those in the lists (see Section 3.1.1).

print(x)
## 1

### 3.2.2 Modification

Unlike lists, tuplets are inalterable (i.e. cannot be modified after they have been created):

x = 1
## Error in py_call_impl(callable, dots$args, dots$keywords): TypeError: 'tuple' object does not support item assignment
##
## Detailed traceback:
##   File "<string>", line 1, in <module>

It is possible to nest tuplets inside another tuple. To do this, parentheses are used:

x = ((1, 4, 9, 16), (1, 8, 26, 64))
print(x)
## ((1, 4, 9, 16), (1, 8, 26, 64))

## 3.3 Sets

Sets are unordered collections of unique elements. The sets are unalterable, not indexed.

To create a set, Python provides the set() function. One or more elements constituting the set are provided, separated by commas and surrounded by braces ({}):

new_set = set({"Marseille", "Aix-en-Provence",
"Nice", "Rennes"})
print(new_set)
## {'Marseille', 'Aix-en-Provence', 'Rennes', 'Nice'}

Equivalently, rather than using the set() function, the set can only be defined using the brackets:

new_set = {"Marseille", "Aix-en-Provence", "Nice", "Rennes"}
print(new_set)
## {'Marseille', 'Aix-en-Provence', 'Rennes', 'Nice'}

On the other hand, if the set is empty, Python returns an error if the set() function is not used: il est nécessaire d’utiliser la fonction set :

empty_set = {}
type(empty_set)
## <class 'dict'>

The type of the object we have just created is not set but dict (i.e. Section 3.4). Also, to create the empty set, we use set():

empty_set = set()
print(type(empty_set))
## <class 'set'>

During the creation of a set, if there are duplicates in the values provided, these will be deleted to keep only one value:

new_set = set({"Marseille", "Aix-en-Provence", "Nice", "Marseille", "Rennes"})
print(new_set)
## {'Marseille', 'Aix-en-Provence', 'Rennes', 'Nice'}

The length of a set is obtained using the len() function:

print(len(new_set))
## 4

### 3.3.1 Modifications

To add an element to a set, Python offers the add() method:

new_set.add("Toulon")
print(new_set)
## {'Aix-en-Provence', 'Marseille', 'Toulon', 'Rennes', 'Nice'}

new_set.add("Toulon")
print(new_set)
## {'Aix-en-Provence', 'Marseille', 'Toulon', 'Rennes', 'Nice'}

#### 3.3.1.2 Deletion

To remove a value from a set, Python offers the method remove():

new_set.remove("Toulon")
print(new_set)
## {'Aix-en-Provence', 'Marseille', 'Rennes', 'Nice'}

If the value is not present in the set, Python returns an error message:

new_set.remove("Toulon")
## Error in py_call_impl(callable, dots$args, dots$keywords): KeyError: 'Toulon'
##
## Detailed traceback:
##   File "<string>", line 1, in <module>
print(new_set)
## {'Aix-en-Provence', 'Marseille', 'Rennes', 'Nice'}

### 3.3.2 Belonging test

One of the advantages of sets is the quick search for presence or absence of values (faster than in a list). As with the lists, the belonging tests are performed using the operator in:

print("Marseille" in new_set)
## True
print("Paris" in new_set)
## False

### 3.3.3 Copying a Set

To copy a set, as for lists (c.f. Section ??), the equality sign should not be used. Copying a set is done using the copy() method:

new_set = set({"Marseille", "Aix-en-Provence", "Nice"})
y = new_set.copy()
print("y : ", y)
## y :  {'Marseille', 'Toulon', 'Aix-en-Provence', 'Nice'}
print("set : ", new_set)
## set :  {'Marseille', 'Aix-en-Provence', 'Nice'}

### 3.3.4 Conversion to a List

One of the interests of sets is that they contain unique elements. Also, when you want to obtain the distinct elements of a list, it is possible to convert it into a set (with the set() function), then to convert the set into a list (with the list() function):

my_list = ["Marseille", "Aix-en-Provence", "Marseille", "Marseille"]
print(my_list)
## ['Marseille', 'Aix-en-Provence', 'Marseille', 'Marseille']
my_set = set(my_list)
print(my_set)
## {'Marseille', 'Aix-en-Provence'}
my_new_list = list(my_set)
print(my_new_list)
## ['Marseille', 'Aix-en-Provence']

## 3.4 Dictionaries

Python dictionaries are an implementation of key-value objects, the keys being indexed.

Keys are often text, values can be of different types and structures.

To create a dictionary, you can proceed by using braces ({}). As encountered in the Section 3.3, if we evaluate the following code, we get a dictionary :

empty_dict = {}
print(type(empty_dict))
## <class 'dict'>

To create a dictionary with entries, the braces can be used. Each entry is separated by commas, and the key is distinguished from the associated value by two points (:):

my_dict = { "nom": "Kyrie",
"prenom": "John",
"naissance": 1992,
"equipes": ["Cleveland", "Boston"]}
print(my_dict)
## {'nom': 'Kyrie', 'prenom': 'John', 'naissance': 1992, 'equipes': ['Cleveland', 'Boston']}

It is also possible to create a dictionary using the dict() function, by providing a sequence of key-values:

x = dict([("Julien-Yacine", "Data-scientist"),
("Sonia", "Director")])
print(x)
## {'Julien-Yacine': 'Data-scientist', 'Sonia': 'Director'}

### 3.4.1 Extraction of the Elements

Extraction from dictionaries is based on the same principle as for lists and tuples (see Section @ref(#structure-liste-extraction)). However, the extraction of an element from a dictionary is not based on its position in the dictionary, but by its key:

print(my_dict["prenom"])
## John
print(my_dict["equipes"])
## ['Cleveland', 'Boston']

If the extraction is done by a key not present in the dictionary, an error will be returned:

print(my_dict["age"])
## Error in py_call_impl(callable, dots$args, dots$keywords): KeyError: 'age'
##
## Detailed traceback:
##   File "<string>", line 1, in <module>

You can test the presence of a key with the operator in:

print("prenom" in my_dict)
## True
print("age" in my_dict)
## False

The extraction of values can also be done using the get() method, which returns a None value if the key is not present:

print(my_dict.get("prenom"))
## John
print(my_dict.get("age"))
## None

### 3.4.2 Keys and values

Using the key() method, the keys of the dictionary can be accessed:

the_keys = my_dict.keys()
print(the_keys)
## dict_keys(['nom', 'prenom', 'naissance', 'equipes'])
print(type(the_keys))
## <class 'dict_keys'>

It is then possible to transform this key enumeration into a list:

the_keys_list = list(the_keys)
print(the_keys_list)
## ['nom', 'prenom', 'naissance', 'equipes']

The values() method provides the dictionary values:

the_values = my_dict.values()
print(the_values)
## dict_values(['Kyrie', 'John', 1992, ['Cleveland', 'Boston']])
print(type(the_values))
## <class 'dict_values'>

The items() method provides keys and values in the form of tuples:

the_items = my_dict.items()
print(the_items)
## dict_items([('nom', 'Kyrie'), ('prenom', 'John'), ('naissance', 1992), ('equipes', ['Cleveland', 'Boston'])])
print(type(the_items))
## <class 'dict_items'>

### 3.4.3 Search for Belonging

Thanks to the methods keys(), values() and items(), it is easy to search for the presence of objects in a dictionary.

print("age" in the_keys)
## False
print("nom" in the_keys)
## True
print(['Cleveland', 'Boston'] in the_values)
## True

### 3.4.4 Modification

#### 3.4.4.1 Replacement

To replace the value associated with a key, the brackets ([]) and the equality sign (=) can be used.

For example, to replace the values associated with the team key:

my_dict["equipes"] = ["Montclair Kimberley Academy",
"Cleveland Cavaliers", "Boston Celtics"]
print(my_dict)
## {'nom': 'Kyrie', 'prenom': 'John', 'naissance': 1992, 'equipes': ['Montclair Kimberley Academy', 'Cleveland Cavaliers', 'Boston Celtics']}

Adding an element to a dictionary can be done with brackets ([]) and the equality sign (=):

my_dict["taille_cm"] = 191
print(my_dict)
## {'nom': 'Kyrie', 'prenom': 'John', 'naissance': 1992, 'equipes': ['Montclair Kimberley Academy', 'Cleveland Cavaliers', 'Boston Celtics'], 'taille_cm': 191}

To add the content of another dictionary to a dictionary, Python offers the update() method.

Let’s create a second dictionary first:

second_dict = {"masse_kg" : 88, "debut_nba" : 2011}
print(second_dict)
## {'masse_kg': 88, 'debut_nba': 2011}

Let’s add the content of this second dictionary to the first:

my_dict.update(second_dict)
print(my_dict)
## {'nom': 'Kyrie', 'prenom': 'John', 'naissance': 1992, 'equipes': ['Montclair Kimberley Academy', 'Cleveland Cavaliers', 'Boston Celtics'], 'taille_cm': 191, 'masse_kg': 88, 'debut_nba': 2011}

If the second dictionary is subsequently modified, it will not affect the first:

second_dict["poste"] = "PG"
print(second_dict)
## {'masse_kg': 88, 'debut_nba': 2011, 'poste': 'PG'}
print(my_dict)
## {'nom': 'Kyrie', 'prenom': 'John', 'naissance': 1992, 'equipes': ['Montclair Kimberley Academy', 'Cleveland Cavaliers', 'Boston Celtics'], 'taille_cm': 191, 'masse_kg': 88, 'debut_nba': 2011}

#### 3.4.4.3 Deleting elements

There are several ways to delete an element in a dictionary. For example, with the operator del :

del my_dict["debut_nba"]
print(my_dict)
## {'nom': 'Kyrie', 'prenom': 'John', 'naissance': 1992, 'equipes': ['Montclair Kimberley Academy', 'Cleveland Cavaliers', 'Boston Celtics'], 'taille_cm': 191, 'masse_kg': 88}

It is also possible to use the pop() method:

res = my_dict.pop("masse_kg")
print(my_dict)
## {'nom': 'Kyrie', 'prenom': 'John', 'naissance': 1992, 'equipes': ['Montclair Kimberley Academy', 'Cleveland Cavaliers', 'Boston Celtics'], 'taille_cm': 191}

In the previous instruction, we added an assignment of the result of applying the pop() method to a variable named res. As can be seen, the pop() method, in addition to deleting the key, returned the associated value:

print(res)
## 88

### 3.4.5 Copy of a Dictionary

To copy a dictionary, and not create a reference (which is the case if you use the equality sign), Python provides, as for sets, a copy() method:

d = {"Marseille": 13, "Rennes" : 35}
d2 = d.copy()
d2["Paris"] = 75
print("d: ", d)
## d:  {'Marseille': 13, 'Rennes': 35}
print("d2: ", d2)
## d2:  {'Marseille': 13, 'Rennes': 35, 'Paris': 75}

### 3.4.6 Exercise

1. Create a dictionary named photo, including the following key-value pairs:

1. key: id, value: 1,
2. key: description, value: A photo of the Old Port of Marseille,
3. key: loc, value: a list in which the following coordinates are given 5.3772133, 43.302424.
2. add the following key-value pair to the photo dictionary: key : user, value : bob.

3. Look for an entry with a key that is worth description in the photo dictionary. If this is the case, display the corresponding entry (key and value).

4. Delete the entry in photo whose key is user.

5. Modify the value of the entry loc in the photo dictionary, to propose a new list, whose coordinates are as follows: 5.3692712 and 43.2949627.