• Aucun résultat trouvé

Les séquences

Dans le document Python Python (Page 103-113)

Une séquence est une collection finie d’éléments ordonnés, indexés par des nombres positifs. Ces nombres varient de 0 à n-1 pour une séquence contenant n éléments. La notation pour se référer au ième élément de la séquence est :

Il est aussi possible d’utiliser des index négatifs pour se référer aux éléments, en les faisant varier de -n à -1. Le dernier élément de la séquence devient :

et le premier :

Les éléments d’une séquence peuvent être découpés en tranches en formant des sous-séquences. Par exemple, sequence[u:v] est une séquence qui est une sous-partie de sequence, de l’élément d’index u inclus, à l’élément d’index v exclus. La nouvelle séquence obtenue devient une séquence à part entière et de même type. La notation de certaines tranches est simplifiée par la double indexation positive et négative vue précédemment. Par exemple, obtenir la tranche qui contient tous les éléments d’une séquence, excepté le premier et le dernier se note :

Il existe un système de tranches étendu pour certains types de listes qui permet d’insérer un troisième paramètre qui définit le pas. sequence[u:v:w] est équivalent à

sequence[i-1]

sequence[-1]

sequence[-n]

sequence[1:-1].

sequence[u:v]mais seuls les éléments multiples de wseront conservés, c’est-à-dire que pour tout index i supérieur ou égal à u et inférieur à v, sequence[i] sera con-servé si i = u + n*w.

Python fournit quelques primitives de manipulation communes à tous les types de séquences :

len() : permet de récupérer le nombre d’éléments de la séquence ;

min() et max() : renvoient les éléments de valeurs minimum et maximum ;

sum() : renvoie la somme des éléments, lorsque tous les éléments de la liste ont des types qui peuvent être additionnés.

Il existe deux sortes de séquences :

• les séquences immuables, qui ne peuvent plus être modifiées après création ;

• les séquences modifiables.

Les séquences immuables

Les séquences immuables sont des objets dont la valeur ne peut plus être modifiée après création.

Ce sont :

• les chaînes de caractères de type str nommées string ;

• les chaînes de caractères Unicode, nommées unicode ;

• les listes immuables d’éléments hétérogènes, de type tuple et nommées tuples ;

• le nouveau type bytes;

• le type frozenset. strings et unicode

Les strings sont des séquences de caractères. Un caractère est une valeur codée sur 8 bits, pour représenter une valeur comprise entre 0 et 255. Ce qui correspond à un signe de la table ASCII (0 et 127) ou de la table étendue (128 à 255) pour les valeurs supérieures.

Contrairement à d’autre langages, il n’existe pas en Python de type spécifique pour un caractère, et un caractère n’est rien d’autre qu’une séquence string de longueur 1.

Il existe cependant deux primitives spécifiques aux caractères, qui permettent de faire la conversion entre le caractère et sa valeur entière : ord() et chr().

Utilisation de chr() et ord()

>>> chr(97) 'a'

Les chaînes unicode fonctionnent de la même manière, mais ont une plage de valeurs plus étendue, puisqu’un signe Unicode peut représenter une valeur sur 16 ou 32 bits. Il n’existe pas de fonction chr() pour les chaînes unicode, mais une fonction spécifique unichr(). La conversion inverse reste possible avec ord().

La conversion entre chaînes string et unicode est possible grâce aux méthodes

encode() et decode() et aux primitives unicode() et str(). Le principe de conver-sion est relativement simple :

Une chaîne unicode peut être convertie en sa correspondance en string avec la méthode encode() ou la fonction str(). Cette correspondance n’est pas bijective, puisque l’Unicode est en quelque sorte un regroupement de toutes les tables de carac-tères existantes. Il est donc nécessaire d’utiliser pour la conversion une table de cor-respondance, nommée codec, qui permet de convertir une chaîne unicode en son équivalent en fonction d’un jeu de caractères donné. Ce jeu de caractères est spéci-fique à chaque groupe alphabétique de langues et celui utilisé pour le français est l’ISO-8859-15. Si l’une des valeurs Unicode n’existe pas dans le codec utilisé, une erreur UnicodeEncodeError est retournée.

>>> ord('z') 122

>>> ord('Z') 90

>>> chr(90) 'Z'

Figure 4–1

Schéma de correspondance unicode-string

Essais d’encodage

La conversion de chaîne string vers unicode, appelée décodage, est basée sur le même principe.

Essais de décodage

La primitive unicode peut être utilisée au même titre que la méthode decode, car elle prend en deuxième paramètre le nom du codec, contrairement à str.

Opérateur d’interpolation

Les objets de type string et unicode possèdent un opérateur d’interpolation, ou opérateur de formatage, qui permet de convertir des marqueurs disposés dans la chaîne de caractères par des valeurs fournies à la suite.

L’écriture est de la forme objet unicode ou string % valeurs, où valeurs est un tuple contenant l’ensemble des valeurs à utiliser dans le formatage.

S’il n’y a qu’une seule valeur, l’élément peut être directement placé après l’opérateur

modulo.

>>> encode = u'je m\'apprête à être encodé'.encode('ISO-8859-15')

>>> print(encode)

je m'apprête à être encodé

>>> u'je m\'apprête à être encodé'.encode('ISO-2022-KR') Traceback (most recent call last):

File "<stdin>", line 1, in ?

UnicodeEncodeError: 'iso2022_kr' codec can't encode character u'\xea' in position 9: illegal multibyte sequence

À RETENIR Utilisation de str pour les conversions de chaînes

La primitive str n’a pas été utilisée ici car elle ne permet pas de convertir une chaîne unicode vers une chaîne string uniquement avec le codec par défaut, c’est-à-dire ascii. Si la chaîne unicode n’avait été composée que de caractères de la table ascii, cette conversion aurait fonctionné.

>>> string = 'je m\'apprête à être décodé, j\'ai peur'

>>> string.decode('ISO-8859-15')

u"je m'appr\xeate \xe0 \xeatre d\xe9cod\xe9, j'ai peur"

>>> unicode(string, 'ISO-8859-15')

u"je m'appr\xeate \xe0 \xeatre d\xe9cod\xe9, j'ai peur"

Formatage de chaîne

À chaque expression précédée d’un %, appelé marqueur de formatage, doit corres-pondre une valeur de formatage dans le tuple fourni.

L’expression est de la forme %[P]c, où c est un caractère qui détermine le type de valeur et P un éventuel paramètre supplémentaire, indiquant la précision à utiliser pour la valeur à formater.

La précision est représentée par un entier préfixé par un point, qui spécifie le nombre de chiffres significatifs après la virgule.

Les caractères de formatage sont :

%d : entier décimal signé ;

%o : octal non signé ;

%u : décimal non signé ;

%x ou %X: valeur hexadécimale, préfixée respectivement par 0x ou 0X ;

%e ou %E : valeur à virgule flottante, de la forme xev ou xEv ;

%f ou F% : réel ;

%g ou %G : pour les valeurs à virgule flottante, équivalent à %e ou %E si l’exposant est supérieur à -4 ou inférieur à la précision, sinon équivalent à %f ;

%c : un seul caractère (sous la forme d’un string ou d’un entier) ;

%r : renvoie le résultat de la primitive repr() ;

%s : renvoie le résultat de la primitive str() ;

%% : permet d’utiliser le caractère % dans une chaîne formatée.

Exemples de formatages

Cette notation s’avère parfois complexe lorsqu’il y a beaucoup d’éléments à rem-placer, et il est possible d’utiliser des formatages nommés avec un dictionnaire.

>>> print("Bonjour Madame %s" % 'Plaindozeille') Bonjour Madame Plaindozeille

>>> print("Cet objet coûte %d euros, Madame %s" % (234, 'Plaindozeille'))

Cet objet coûte 234 euros, Madame Plaindozeille

>>> print('%.2f euros' % 2.394765) 2.39 euros

>>> print('%E euros' % 2.394765) 2.394765E+00 euros

>>> print('%s euros' % '2.394') 2.394 euros

>>> print('%d euros' % 2.394) 2 euros

Formatage par méthode classique puis par dictionnaire

Le formatage «%s» devient «%(label)s» où label est une clé dans le dictionnaire passé à l’opérateur «%».

Tuples

Les tuples sont des séquences qui contiennent des éléments de types hétérogènes.

Chacun des éléments est séparé par une virgule et l’ensemble est défini par des parenthèses. Une fois l’objet créé, il est impossible de modifier sa valeur. Cette con-trainte permet d’utiliser ce type d’objet dans des cas de programmation précis que nous verrons par la suite. Pour pouvoir modifier les éléments d’un tuple, il faut donc en créer un nouveau qui le remplacera.

Les tuples composés d’un seul élément ont une écriture un peu particulière puisqu’il est nécessaire d’ajouter une virgule après l’élément, sans quoi l’analyseur syntaxique de Python ne le considérera pas comme un tuple mais comme l’élément lui-même, et supprimera les parenthèses qu’il analyserait comme superflues.

Manipulation de tuples

>>> "Remplacement de %s par %s. Oui %s par %s, vraiment %s." % \ ... ('ce mot', 'ce mot-ci', 'ce mot', 'ce mot-ci', 'ce mot-ci') 'Remplacement de ce mot par ce mot-ci. Oui ce mot par ce mot-ci, vraiment ce mot-ci.'

>>> ("Remplacement de %(old)s par %(new)s. Oui %(old)s par %(new)s, "

... "vraiment %(old)s." % {'old': 'ce mot', 'new': 'ce mot ci'}) 'Remplacement de ce mot par ce mot-ci. Oui ce mot par ce mot-ci, vraiment ce mot.'

>>> tuple() ()

>>> tuple('a') ('a',)

>>> color_and_note = ('rouge', 12, 'vert', 14, 'bleu', 9)

>>> colors = color_and_note[::2]

('rouge', 12, 'vert', 14, 'bleu', 9, 'violet')

>>> print('violet') violet

>>> print('violet',) ('violet',)

L’oubli de la virgule dans un tuple à un élément, pour différencier ('violet',) de

'violet', est une erreur courante de programmation.

bytes

Le type bytes est sous Python 2.6 un simple alias vers le type str. Il permet une transition en douceur vers Python 3.

Il devient réellement différent dans Python 3 et permet de manipuler des entiers de 0 à 127 correspondants à la table ASCII. Il peut être initialisé par des valeurs dans une séquence préfixée de b, ou par une chaîne de caractères de type str.

Manipulation de bytes sous Python 3

Pour être initialisé avec un objet de type str, il est nécessaire d’utiliser le constructeur de

bytes et de préciser l’encodage de la chaîne pour que Python puisse traduire la chaîne.

Initialisation avec une simple chaîne

frozenset

Le type frozenset est une version immuable du type set. Il est présenté avec le type

set dans la prochaine section.

Les séquences modifiables

Les séquences modifiables implémentent un certain nombre de méthodes qui permet-tent d’ajouter, de supprimer ou de modifier chacun des éléments qui les composent.

Le langage propose plusieurs types de séquences modifiables :

list, le type le plus classique ;

bytearray, qui permet de manipuler des bytes ;

set, qui définit une séquence non ordonnée ;

array, qui implémente une liste d’éléments homogènes simples, comme les entiers ou chaînes de caractères, du moment qu’ils sont dans la bibliothèque standard.

>>> data = b'\xc1\xc2'

>>> data b'\xc1\xc2'

>>> data = b'some bytes'

>>> data b'some bytes'

>>> data = bytes('some bytes', 'utf-8')

>>> data b'some bytes'

Le type list

Dans une liste, chaque élément est séparé par une virgule et l’ensemble est entouré par des crochets. Une liste vide se note donc [].

Manipulation de list

Le tableau ci-dessous regroupe l’ensemble des méthodes applicables aux listes, et complète les primitives communes à toutes les séquences. Pour les méthodes, les paramètres optionnels sont notés en italique :

>>> list()

append(e) Permet d’ajouter un élément e en fin de liste.

>>> a = [1, 3, 'b']

>>> a.append('t')

>>> print(a) [1, 3, 'b', 't']

extend(L) Permet d’ajouter les éléments d’une seconde liste L en fin de liste.

>>> a = [1, 2, 3]

remove(e) Retire le premier élément de la liste qui a la même valeur que celle fournie. Si aucun élément n’est trouvé, une erreur est retournée.

File "<stdin>", line 1, in

<module>?

ValueError: list.remove(x): x not in list

pop(i) Retire l’élément d’index i de la liste et le

index(e) Renvoie l’index du premier élément dont la valeur est e. Une erreur est renvoyée si

File "<stdin>", line 1, in

<module>?

ValueError: list.index(x): x not in list

count(e) Indique le nombre d’occurrences de l’élé-ment e.

sort(fonc) Trie les éléments de la liste. Le paramètre optionnel fonc est un nom de fonction qui sera utilisé pour comparer deux à deux les éléments de la liste. S’il est omis, un tri par défaut basé sur les valeurs bru-tes des éléments est appliqué.

Le principe de comparaison par valeurs brutes sera explicité dans le chapitre trai-tant des opérateurs.

reverse() Retourne la liste. Le premier élément devient le dernier, le deuxième

Tableau 4–2 Méthodes pour les listes (suite)

Nom Description Exemple

bytearray

Le type bytearray est équivalent au type bytes mais permet de modifier les don-nées. Il s’instancie avec une liste d’entiers, une chaîne binaire ou une chaîne classique du moment que l’encodage est fourni.

Initialisation d’un bytearray

bytearray implémente certaines méthodes du type str, comme startswith,

endswith ou encore find.

Il permet aussi de manipuler les données comme une séquence, et implémente cer-taines méthodes de list, comme append, pop ou encore sort.

Manipulation de bytearray

set

Le type set est une séquence non ordonnée d’objets hashable uniques. Un objet has-hable est un objet qui implémente la méthode spéciale __hash__, qui renvoie une valeur unique pendant toute la durée de vie de l’objet. En d’autres termes, les objets hashable sont tous des objets de valeur constante.

À SAVOIR Supprimer directement un élément d’une séquence

Pour supprimer directement l’élément d’index i d’une séquence s modifiable, il est possible d’utiliser la primitive del en utilisant la notation : del s[i]

>>> array = bytearray([1, 78, 76])

>>> array

bytearray(b'\x01NL')

>>> bytearray(b'some data') bytearray(b'some data')

>>> bytearray('some data', 'utf8') bytearray(b'some data')

>>> array = bytearray([1, 78, 76])

>>> array.startswith(b'\x01') True

>>> array[2]

76

>>> array.append(12)

>>> array

bytearray(b'\x01NL\x0c')

>>> array.reverse()

>>> array

bytearray(b'\x0cLN\x01')

La primitive hash permet de renvoyer la valeur retournée par méthode __hash__ de l’objet et de provoquer une erreur si l’objet n’en a pas, c’est-à-dire s’il n’est pas constant.

Manipulation de hash

Cette restriction permet à set d’être beaucoup plus performant qu’une séquence classique pour certains opérateurs, comme in, car il construit en mémoire un index des éléments.

Opérateur in sur set et list

Les méthodes disponibles avec set sont celles des séquences.

frozenset est un sous-type de set qui est immuable et permet de figer le contenu de la séquence et d’offrir de nouvelles méthodes de comparaisons puissantes et rapides.

Dans le document Python Python (Page 103-113)