# 1.2.2. Basic types¶

## 1.2.2.1. Numerical types¶

Tip

Python supports the following numerical, scalar types:

Integer:
```>>> 1 + 1
2
>>> a = 4
>>> type(a)
<class 'int'>
```
Floats:
```>>> c = 2.1
>>> type(c)
<class 'float'>
```
Complex:
```>>> a = 1.5 + 0.5j
>>> a.real
1.5
>>> a.imag
0.5
>>> type(1. + 0j)
<class 'complex'>
```
Booleans:
```>>> 3 > 4
False
>>> test = (3 > 4)
>>> test
False
>>> type(test)
<class 'bool'>
```

Tip

A Python shell can therefore replace your pocket calculator, with the basic arithmetic operations `+`, `-`, `*`, `/`, `%` (modulo) natively implemented

```>>> 7 * 3.
21.0
>>> 2**10
1024
>>> 8 % 3
2
```

Type conversion (casting):

```>>> float(1)
1.0
```

## 1.2.2.2. Containers¶

Tip

Python provides many efficient types of containers, in which collections of objects can be stored.

### Lists¶

Tip

A list is an ordered collection of objects, that may have different types. For example:

```>>> colors = ['red', 'blue', 'green', 'black', 'white']
>>> type(colors)
<class 'list'>
```

Indexing: accessing individual objects contained in the list:

```>>> colors[2]
'green'
```

Counting from the end with negative indices:

```>>> colors[-1]
'white'
>>> colors[-2]
'black'
```

Warning

Indexing starts at 0 (as in C), not at 1 (as in Fortran or Matlab)!

Slicing: obtaining sublists of regularly-spaced elements:

```>>> colors
['red', 'blue', 'green', 'black', 'white']
>>> colors[2:4]
['green', 'black']
```

Warning

Note that `colors[start:stop]` contains the elements with indices `i` such as `start<= i < stop` (`i` ranging from `start` to `stop-1`). Therefore, `colors[start:stop]` has `(stop - start)` elements.

Slicing syntax: `colors[start:stop:stride]`

Tip

All slicing parameters are optional:

```>>> colors
['red', 'blue', 'green', 'black', 'white']
>>> colors[3:]
['black', 'white']
>>> colors[:3]
['red', 'blue', 'green']
>>> colors[::2]
['red', 'green', 'white']
```

Lists are mutable objects and can be modified:

```>>> colors[0] = 'yellow'
>>> colors
['yellow', 'blue', 'green', 'black', 'white']
>>> colors[2:4] = ['gray', 'purple']
>>> colors
['yellow', 'blue', 'gray', 'purple', 'white']
```

Note

The elements of a list may have different types:

```>>> colors = [3, -200, 'hello']
>>> colors
[3, -200, 'hello']
>>> colors[1], colors[2]
(-200, 'hello')
```

Tip

For collections of numerical data that all have the same type, it is often more efficient to use the `array` type provided by the `numpy` module. A NumPy array is a chunk of memory containing fixed-sized items. With NumPy arrays, operations on elements can be faster because elements are regularly spaced in memory and more operations are performed through specialized C functions instead of Python loops.

Tip

Python offers a large panel of functions to modify lists, or query them. Here are a few examples; for more details, see https://docs.python.org/3/tutorial/datastructures.html#more-on-lists

```>>> colors = ['red', 'blue', 'green', 'black', 'white']
>>> colors.append('pink')
>>> colors
['red', 'blue', 'green', 'black', 'white', 'pink']
>>> colors.pop() # removes and returns the last item
'pink'
>>> colors
['red', 'blue', 'green', 'black', 'white']
>>> colors.extend(['pink', 'purple']) # extend colors, in-place
>>> colors
['red', 'blue', 'green', 'black', 'white', 'pink', 'purple']
>>> colors = colors[:-2]
>>> colors
['red', 'blue', 'green', 'black', 'white']
```

Reverse:

```>>> rcolors = colors[::-1]
>>> rcolors
['white', 'black', 'green', 'blue', 'red']
>>> rcolors2 = list(colors) # new object that is a copy of colors in a different memory area
>>> rcolors2
['red', 'blue', 'green', 'black', 'white']
>>> rcolors2.reverse() # in-place; reversing rcolors2 does not affect colors
>>> rcolors2
['white', 'black', 'green', 'blue', 'red']
```

Concatenate and repeat lists:

```>>> rcolors + colors
['white', 'black', 'green', 'blue', 'red', 'red', 'blue', 'green', 'black', 'white']
>>> rcolors * 2
['white', 'black', 'green', 'blue', 'red', 'white', 'black', 'green', 'blue', 'red']
```

Tip

Sort:

```>>> sorted(rcolors) # new object
['black', 'blue', 'green', 'red', 'white']
>>> rcolors
['white', 'black', 'green', 'blue', 'red']
>>> rcolors.sort()  # in-place
>>> rcolors
['black', 'blue', 'green', 'red', 'white']
```

### Strings¶

Different string syntaxes (simple, double or triple quotes):

```s = 'Hello, how are you?'
s = "Hi, what's up"
s = '''Hello,
how are you'''         # tripling the quotes allows the
# string to span more than one line
s = """Hi,
what's up?"""
```
```In [2]: 'Hi, what's up?'
Cell In[2], line 1
'Hi, what's up?'
^
SyntaxError: unterminated string literal (detected at line 1)
```

This syntax error can be avoided by enclosing the string in double quotes instead of single quotes. Alternatively, one can prepend a backslash to the second single quote. Other uses of the backslash are, e.g., the newline character `\n` and the tab character `\t`.

Tip

Strings are collections like lists. Hence they can be indexed and sliced, using the same syntax and rules.

Indexing:

```>>> a = "hello"
>>> a[0]
'h'
>>> a[1]
'e'
>>> a[-1]
'o'
```

Tip

(Remember that negative indices correspond to counting from the right end.)

Slicing:

```>>> a = "hello, world!"
>>> a[3:6] # 3rd to 6th (excluded) elements: elements 3, 4, 5
'lo,'
>>> a[2:10:2] # Syntax: a[start:stop:step]
'lo o'
>>> a[::3] # every three characters, from beginning to end
'hl r!'
```

Tip

Accents and special characters can also be handled as in Python 3 strings consist of Unicode characters.

A string is an immutable object and it is not possible to modify its contents. One may however create new strings from the original one.

```In [3]: a = "hello, world!"

In [4]: a.replace('l', 'z', 1)
Out[4]: 'hezlo, world!'
```

Tip

Strings have many useful methods, such as `a.replace` as seen above. Remember the `a.` object-oriented notation and use tab completion or `help(str)` to search for new methods.

Python offers advanced possibilities for manipulating strings, looking for patterns or formatting. The interested reader is referred to https://docs.python.org/3/library/stdtypes.html#string-methods and https://docs.python.org/3/library/string.html#format-string-syntax

String formatting:

```>>> 'An integer: %i; a float: %f; another string: %s' % (1, 0.1, 'string') # with more values use tuple after %
'An integer: 1; a float: 0.100000; another string: string'

>>> i = 102
>>> filename = 'processing_of_dataset_%d.txt' % i   # no need for tuples with just one value after %
>>> filename
'processing_of_dataset_102.txt'
```

### Dictionaries¶

Tip

A dictionary is basically an efficient table that maps keys to values.

```>>> tel = {'emmanuelle': 5752, 'sebastian': 5578}
>>> tel['francis'] = 5915
>>> tel
{'emmanuelle': 5752, 'sebastian': 5578, 'francis': 5915}
>>> tel['sebastian']
5578
>>> tel.keys()
dict_keys(['emmanuelle', 'sebastian', 'francis'])
>>> tel.values()
dict_values([5752, 5578, 5915])
>>> 'francis' in tel
True
```

Tip

It can be used to conveniently store and retrieve values associated with a name (a string for a date, a name, etc.). See https://docs.python.org/3/tutorial/datastructures.html#dictionaries for more information.

A dictionary can have keys (resp. values) with different types:

```>>> d = {'a':1, 'b':2, 3:'hello'}
>>> d
{'a': 1, 'b': 2, 3: 'hello'}
```

### More container types¶

Tuples

Tuples are basically immutable lists. The elements of a tuple are written between parentheses, or just separated by commas:

```>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> u = (0, 2)
```

Sets: unordered, unique items:

```>>> s = set(('a', 'b', 'c', 'a'))
>>> s
{'a', 'b', 'c'}
>>> s.difference(('a', 'b'))
{'c'}
```

## 1.2.2.3. Assignment operator¶

Tip

Assignment statements are used to (re)bind names to values and to modify attributes or items of mutable objects.

In short, it works as follows (simple assignment):

1. an expression on the right hand side is evaluated, the corresponding object is created/obtained

2. a name on the left hand side is assigned, or bound, to the r.h.s. object

Things to note:

• A single object can have several names bound to it:

```In [5]: a = [1, 2, 3]

In [6]: b = a

In [7]: a
Out[7]: [1, 2, 3]

In [8]: b
Out[8]: [1, 2, 3]

In [9]: a is b
Out[9]: True

In [10]: b[1] = 'hi!'

In [11]: a
Out[11]: [1, 'hi!', 3]
```
• to change a list in place, use indexing/slices:

```In [12]: a = [1, 2, 3]

In [13]: a
Out[13]: [1, 2, 3]

In [14]: a = ['a', 'b', 'c'] # Creates another object.

In [15]: a
Out[15]: ['a', 'b', 'c']

In [16]: id(a)
Out[16]: 140681556919488

In [17]: a[:] = [1, 2, 3] # Modifies object in place.

In [18]: a
Out[18]: [1, 2, 3]

In [19]: id(a)
Out[19]: 140681556919488
```
• the key concept here is mutable vs. immutable

• mutable objects can be changed in place

• immutable objects cannot be modified once created