4  Les types de base (built-in)

Python propose plusieurs types, ou plutôt familles de types, de base (built-in).

Les scalaires sont représentés par les types numériques.

Les types de données qui représentent plusieurs données sont les collections.

4.1 Les types numériques

En Python, nous avons 3 types numériques :

  • int qui représente les entiers
  • float pour les réels
  • complex pour les nombres complexe.

Le type booléens (bool) représente les notions de vrai et faux et prennent deux valeurs : True et False.

De manière générale en Python, le type de la donnée est déduite par l’interpréteur. Les types built-in ont la particularité d’être déclarés par leur valeur. Néanmoins, il existe aussi des fonctions pour initialiser ces données. Ces fonctions peuvent également convertir un type dans le type correspondant au nom de la fonction : int(var), float(var) ou complex(var1, var2).

Ci-dessous, vous avez un exemple de déclaration de types numérique

1answer = 42
2answer = 42.0
1
Déclaration d’un entier ( int)
2
Déclaration d’un réel (Float)
In [10]: var_int = int(42.2)
In [11]: var_int = 42

In [12]: var_float = float(3)
In [13]: var_float = 3.
In [14]: var_float = 3.14

In [15]: var_cpx = complex(42, 2)
In [16]: var_cpx = 42 + 2j
In [17]: var_cpx.real
Out[17]: 42.0
In [18]: var_cpx.imag
Out[18]: 2.0

En Python, il n’y a pas de taille maximum des entiers. La curiosité est que si sa valeur est comprise entre -2^(n-1) et 2^(n-1)-1, il est géré en registre, sinon en mémoire. Les réels ont une taille correspondant à un double en C.

4.2 Opérateurs arithmétiques

Python propose les opérateurs arithmétiques classiques ainsi que quelques autres.

x + y Addition
x - y Soustraction
x * y Multiplication
x / y Division
x // y Division entière
x % y Reste
-x Opposé
+x Identité
x ** y Puissance

La priorité des opérateurs est la priorité mathématique. À priorité égale, les opérations sont résolues de gauche à droite. Les parenthèses ont la plus grande priorité et permettent de grouper les opérations.

Ces opérateurs sont utilisés entre les types numériques en tant qu’opérateurs mathématiques mais certains peuvent être utilisés avec d’autres types. Ainsi, l’addition de deux chaines de caractères (voir partie sur les collections) produira une chaine de caractères correspondant à la concaténation de ces deux chaines.

4.3 Les opérateurs bitwise

Aussi appelés opérateurs bits à bits, ils sont souvent à tord appelés opérateurs binaires.

Python propose les opérateurs suivants : 

x | y Ou binaire
x ^ y Ou exclusif
x & y Et binaire
x << y Décalage à gauche
x >> y Décalage à droite
~ x Inversion

Ces opérateurs permettent de manipuler la représentation binaire des valeurs, par exemple : 

In [1]: x = 5

In [2]: y = 6

In [3]: res = x | y

In [4]: print(res)
7

5 en binaire est 0b101

6 en binaire est 0b110

Donc 0b101 OU BINAIRE 0b110 donne 0b111 soit 7.

Leur intérêt se retrouve surtout dans les opérations usuelles comme dans l’exemple suivant, déterminer si un entier est une puissance de deux (dans cet exemple, 0 est également considéré comme une puissance de 2) :

In [5]: (value & (value - 1)) == 0

4.4 Les collections

Les collections représentent des types qui regroupent une collection de données.

Les collections qui contiennent des éléments ordonnées sont des séquences. Python propose trois types pour les séquences :

  • les chaines de caractères (str)
  • les listes (list)
  • les N-uplets (tuple)

Les collections qui ne sont pas des séquences sont :

  • les ensembles (set)
  • les dictionnaires (dict)

Les collections sont des objets. En plus des opérateurs communs, chaque type a ses méthodes spécifiques qui permettent des actions spécifiques. Souvenez-vous que vous pouvez consulter la documentation de chaque type avec la fonction help().

Toutes les collections peuvent être initialisées par une fonction du nom du type qui, sans paramètre, retournera une collection vide.

4.4.1 Instructions communes

Les différents types de collection, soit str, list, tuple et dict, ont des comportements communs. Les instructions suivantes sont communes à ces différents types. Ainsi, soit my_collection une collection d’un de ces types, x une valeur et n un entier (int).

  • x in my_collection : retourne True si my_collection contient x, sinon False
  • x not in my_collection : retourne False si my_collection contient x, sinon True
  • my_collection1 + my_collection2 : Retourne une concaténation les deux collections du même type.
  • my_collection * n : où n est un entier, retourne une nouvelle collection multiple de l’originale 
  • len(my_collection) : retourne la taille de la collection

4.4.2 Les séquences : accès aux éléments

Concerne : str, list, tuple

Les éléments d’une séquence sont identifiés par leur position. La position d’un élément est représentée par son indice qui est la position en commençant à 0.

Pour accéder à un élément d’une séquence, on utilise son indice entre crochet. Python utilise les indices négatifs afin d’accéder aux éléments à partir de la fin.

In [30]: knights = ["Arthur", "Lancelot", "Robin", "Bedevere", "Galaad"]
In [31]: antagonist = 'Killer Rabbit of Caerbannog'

In [32]: print(knights[2])
Robin

In [33]: print(antagonist[2])
l

In [34]: print(knights[-1])
Galaad

In [35]: print(antagonist[-5])
a

Ceci permet d’illustrer un des adages de Python : “There should be one– and preferably only one –obvious way to do it” ou « Il devrait y avoir une, et de préférence une seule, manière évidente de faire une chose ». Ainsi, une demande du type « quel est le dernier élément de la liste » se traduit par ma_liste[-1].

4.4.3 Modification d’un élément

Concerne : list

Un élément d’une liste peut être remplacé en attribuant une valeur à un indice existant. La valeur référencée par cet indice est alors remplacée par la nouvelle.

In [50]: knights = ["Arthur", "Robin", "Bedevere", "Galaad"]

In [51]: knights[1] = 'Lancelot'
In [52]: print(knights)
['Arthur', 'Lancelot', 'Bedevere', 'Galaad']

Les tuples et les chaines de caractères sont des types immuables. Il est impossible de replacer un de leurs éléments.

4.5 Slicing

Concerne : str, list, tuple

Le slicing permet d’extraire une sous-séquence. Cette opérateur va retourner une nouvelle séquence du même type avec les éléments correspondants à la plage indiquée.

4.5.1 Usage

L’opérateur de slicing ainsi que ses différents usages sont les suivants (seq étant une séquence) :

  • seq[x:y] : extrait une séquence de l’indice x à l’indice y exclu
  • seq[:y] : extrait une séquence de l’indice 0 à l’indice y exclu
  • seq[x:] : extrait une séquence de l’indice x à la fin de la séquence seq
  • seq[x:y:z] : extrait une séquence de l’indice x à l’indice y exclu avec un pas de z.

Les valeurs x, y et z sont toutes optionnelles, seq[:] retournera ainsi une copie de la séquence.

Si les bornes sont en dehors des limites de la séquence, le slicing retournera une séquence vide.

In [2]: knights = ["Arthur", "Lancelot", "Robin", "Bedevere", "Galaad"]

In [3]: knights[2:4]
Out[3]: ['Robin', 'Bedevere']

In [4]: # Récupérons les deux premiers éléments

In [5]: knights[:2]
Out[5]: ['Arthur', 'Lancelot']

In [6]: # Récupérons les éléments à partir du troisième

In [7]: knights[2:]
Out[7]: ['Robin', 'Bedevere', 'Galaad']

In [8]: # Récupérons les deux derniers éléments avec les indices négatifs

In [9]: knights[-2:]
Out[9]: ['Bedevere', 'Galaad']

In [10]: antagonist = 'Killer Rabbit of Caerbannog'

In [11]: antagonist[::2]
Out[11]: 'Kle abto arang'

4.5.2 Mais pourquoi cette exclusion ?

La position des éléments dans une séquence en Python est représenté par leur indice, le premier élément est à l’indice 0. On parle de 0-based indexing. ABC, Algol, Fortran ou Pascal utilisaient le 1-based indexing.

Le slicing permet d’obtenir selon la définition mathématique, un intervalle semi-ouvert à droite. Cela se noterait [x, y[. Pourquoi ce choix d’implémentation ?

Guido Van Rossum s’est exprimé sur ce choix. Il faut savoir que c’est le slicing qui a conduit au choix entre une indexation 0-based ou 1-based. Ce choix repose sur les cas d’usage les plus courants :

  • Obtenir les n premiers éléments
  • Obtenir les n éléments à partir de l’indice i
  • Obtenir des tranches adjacentes à l’aide d’un invariant.

Ces cas sont illustrés ci-dessous

In [12]: n = 2

In [13]: i = 1

In [14]: knights[:2]  # Les deux premiers
Out[14]: ['Arthur', 'Lancelot']

In [15]: knights[i: i + n]  # Les deux après l'indice i
Out[15]: ['Lancelot', 'Robin']

In [16]: # Les deux premiers et les suivants

In [17]: knights[:2]
Out[17]: ['Arthur', 'Lancelot']

In [18]: knights[2:]
Out[18]: ['Robin', 'Bedevere', 'Galaad']