Notre premier objet : les chaînes de caractères

    Publicités

Users Who Are Viewing This Thread (Total: 0, Members: 0, Guests: 0)

Superman

V
Ancien staff
Dec 2, 2009
2,489
0
596
Vous avez dit objet ?

La première question qui risque de vous empêcher de dormir si je n'y réponds pas tout de suite, c'est :
Mais c'est quoi un objet ?
Eh bien j'ai lu beaucoup de définitions très différentes et je n'ai pas trouvé de points communs à toutes ces définitions. Nous allons donc partir d'une définition incomplète, mais qui suffira pour l'instant :

Un objet est une structure de données, comme les variables, qui peut contenir elle-même d'autres variables et fonctions. On étoffera plus loin cette définition, elle suffit bien pour le moment
smile.png
.

Je ne comprends rien. Passe encore qu'une variable en contienne d'autres, après tout les chaînes de caractères contiennent bien des caractères, mais qu'une variable contienne des fonctions... ça rime à quoi ?
blink.gif



Je pourrais passer des heures à expliquer la théorie du concept que vous n'en seriez pas beaucoup plus avancé. J'ai choisi de vous montrer les objets par l'exemple et donc, vous allez très rapidement voir ce que tout cela signifie. Mais vous allez devoir me faire confiance au début sur l'utilité de la méthode objet
smile.png
.

Avant d'attaquer, une petite précision. J'ai dit qu'un objet était un peu comme une variable... en fait, pour être plus exact, il faut dire qu'une variable est un objet
clin.png
. Toutes les variables avec lesquelles nous avons travaillé jusqu'ici sont des objets. Les fonctions que nous avons vues sont également des objets. Tout est objet en Python, gardez-le à l'esprit.

Assez de théorie ! Je vais expliquer tout ça tout de suite et, si je fais bien mon travail, vous devriez comprendre tout ça très rapidement
clin.png
.
Les méthodes de la classe str

Ohlala, j'en vois qui grimacent rien qu'en voyant le titre
heureux.png
. Pas de raison de s'inquiéter !
smile.png
On va aller tout doucement.

Je vais vous poser un problème : comment peut-on mettre une chaîne de caractères en minuscule ? Si vous vous êtes contenté de mon tutoriel, vous ne pourrez pas faire cet exercice, j'ai volontairement évité de trop aborder les chaînes de caractères jusqu'ici. Mais admettons que vous arriviez à coder une fonction prenant en paramètre la chaîne en question. Vous aurez un code qui ressemblera à cela :

Code : Python Console1
2
3
>>> chaine = "NE CRIE PAS SI FORT !"
>>> mettre_en_minuscule(chaine)
'ne crie pas si fort !'




Sachez que dans les anciennes versions de Python, celles qui n'intégraient pas encore l'approche objet, on avait un module spécialisé dans le traitement des chaînes de caractères. On importait ce module et on pouvait appeler la fonction pour mettre en minuscule une chaîne. Ce module existe d'ailleurs encore et reste utilisé pour certains traitements spécifiques. Mais on va découvrir ici une façon de faire différente. Regardez attentivement :

Code : Python Console1
2
3
>>> chaine = "NE CRIE PAS SI FORT !"
>>> chaine.lower() # mettre en minuscule la chaîne
'ne crie pas si fort !'




La fonction lower est une nouveauté pour vous. Vous devez reconnaître le point « . » qui symbolisait déjà, dans le chapitre sur les modules, une relation d'appartenance (a.b signifiait b contenu dans a). Ici c'est la même signification : la fonction lower est une fonction de la variable chaine.

La fonction lower est propre aux chaînes de caractères. Toutes les chaînes peuvent faire appel à cette fonction. Si vous tapez type(chaine) dans l'interpréteur, vous obtenez <class 'str'>. Nous avons dit qu'une variable est issue d'un type de donnée. Je vais à présent reformuler : un objet est issu d'une classe. La classe est une forme de type de donnée, sauf qu'elle permet de définir des fonctions et variables propres au type. C'est pour cela que dans toutes les chaînes de caractères, on peut appeler la fonction lower. C'est tout simplement parce que la fonction lower a été définie dans la classe str. Les fonctions définies dans une classe sont appelées des méthodes.

Récapitulons. Nous avons découvert :

  • Les objets que j'ai présentés comme des variables, pouvant contenir d'autres variables ou fonctions (que l'on appelle méthodes). On appelle une méthode d'un objet grâce à objet.methode() .
  • les classes que j'ai présentées comme des types de données. Une classe est un modèle qui servira à construire un objet ; c'est dans la classe qu'on va définir les méthodes propres à l'objet.


Schématiquement voici le mécanisme qui vous permet d'appeler la méthode lower d'une chaîne :


  1. Les développeurs de Python ont créé la classe str qui sera utilisée pour créer des chaînes de caractères. Dans cette classe, ils ont défini plusieurs méthodes, comme lower, qui pourront être utilisées par n'importe quel objet construit sur cette classe.
  2. Quand vous écrivez chaine = "NE CRIE PAS SI FORT !" , Python reconnaît qu'il doit créer une chaîne de caractères. Il va donc créer un objet d'après la classe (le modèle) qui a été définie à l'étape précédente.
  3. Vous pouvez ensuite appeler toutes les méthodes de la classe str depuis l'objet chaine que vous venez de créer.


Ouf ! Ҫa fait beaucoup de choses nouvelles, du vocabulaire et du concept un peu particulier
smile.png
.

Vous ne voyez peut-être pas encore tout l'intérêt d'avoir des méthodes définies dans une certaine classe. Cela permet d'abord de bien séparer les diverses fonctionnalités (on ne peut mettre en minuscule un nombre entier, ça n'a aucun sens). Ensuite, c'est plus intuitif, une fois passé le choc de la première rencontre
clin.png
.

Bon, on parle, on parle, mais on code pas beaucoup
heureux.png
.

Mettre en forme une chaîne


Non, vous n'allez pas apprendre à mettre une chaîne en gras, souligné, avec une police Verdana de 15px... sachons raison garder, nous ne sommes encore que dans une console
heureux.png
. Nous venons de voir lower, il existe d'autres méthodes... mais avant tout voyons un contexte d'utilisation.

Certains d'entre vous se demandent peut-être l'intérêt de mettre des chaînes en minuscule... alors voici un petit exemple.

Code : Python1
2
3
4
5
6
7
8
chaine = str() # créée une chaîne vide
# on aurait obtenu le même résultat en tapant chaine = ""

while chaine.lower() != "q":
print("Tapez 'Q' pour quitter...")
chaine = input()

print("Merci !")




Vous devez comprendre rapidement ce programme. On demande dans une boucle à l'utilisateur d'entrer la lettre "Q" pour quitter. Tant que l'utilisateur entre une autre lettre, la boucle continue de s'exécuter. Dès que l'utilisateur entre Q, la boucle s'arrête et le programme affiche Merci ! Ҫa devrait vous rappeler quelque chose... direction le TP de la partie 1 pour ceux qui ont la mémoire courte
heureux.png
.

La petite nouveauté est dans le test de la boucle : chaine.lower() != "q". On prend la chaîne entrée par l'utilisateur, on la met en minuscule et on regarde si elle est différente de "q". Cela veut dire que l'utilisateur peut entrer "q" en majuscule ou en minuscule, dans les deux cas la boucle s'arrêtera.

Notez que chaine.lower() retourne la chaîne en minuscule, mais ne modifie pas la chaîne. Cela est très important, nous verrons pourquoi dans le chapitre suivant.

Notez aussi que nous avons appelé la fonction str pour créer une chaîne vide. Je ne vais pas trop compliquer les choses, pas encore, mais sachez qu'appeler ainsi un type comme une fonction permet de créer un objet de la classe. Ici, str() crée un objet « chaîne de caractères ». Nous avons vu dans la première partie int() qui crée aussi un entier (depuis un autre type si nécessaire, ce qui permet de convertir une chaîne en entier par exemple).

Bon, voyons d'autres méthodes. Je vous invite à tester mes exemples (ils sont commentés, mais on retient mieux en essayant par soi-même).
clin.png


Code : Python Console 1
2
3
4
5
6
7
8
9
10
11
12
>>> minuscule = "une chaine en minuscule"
>>> minuscule.upper() # mettre en majuscule
'UNE CHAINE EN MINUSCULE'
>>> minuscule.capitalize() # la première lettre en majuscule
'Une chaine en minuscule'
>>> espaces = " une chaine avec des espaces "
>>> espaces.strip() # on retire les espaces au début et à la fin de la chaîne
'une chaine avec des espaces'
>>> titre = "introduction"
>>> titre.upper().center(20)
' INTRODUCTION '
>>>




La dernière instruction mérite quelques explications. Dans l'ordre :


  • On appelle la méthode upper de l'objet titre. Cette méthode, comme vous l'avez vu plus haut, retourne la chaîne de caractères contenue dans l'objet, en majuscule.
  • On appelle ensuite la méthode center, méthode que nous n'avons pas encore vue et qui permet de centrer une chaîne. On lui passe en paramètre la taille de la chaîne que l'on souhaite obtenir et la méthode, travaillant sur l'objet, va rajouter alternativement une espace au début et à la fin de la chaîne, jusqu'à obtenir la taille demandée. Dans cet exemple, titre contient la chaîne 'introduction', chaîne qui (en minuscule ou en majuscule
    heureux.png
    ) mesure 12 caractères. On demande à center de centrer cette chaîne dans un espace de 20 caractères. La méthode center va donc placer 4 espaces avant le titre, et 4 espaces après, pour faire 20 en tout
    smile.png
    .

    Bon, mais maintenant, sur quel objet travaille center ? Sur titre ? Non. Sur la chaîne retournée par titre.upper(), c'est-à-dire le titre en majuscule. C'est pourquoi on peut chaîner ces deux méthodes : upper, comme la plupart des méthodes de chaînes, travaille sur une chaîne et retourne une chaîne... qui elle aussi va posséder les méthodes propres à une chaîne de caractères. Si ce n'est pas très clair, faites quelques tests, avec titre.upper() et titre.center(20), en passant par une seconde variable si nécessaire, pour vous rendre compte du mécanisme, ce n'est pas bien compliqué.


Je n'ai mis ici que quelques méthodes, il y en a bien d'autres. Vous pouvez en voir la liste dans l'aide, en tapant, dans l'interpréteur : help(str) .

Formater et afficher une chaîne


Attends, on a appris à faire ça depuis cinq bons chapitres ! On va pas tout réapprendre quand même ?


Pas tout, non. Mais nous allons apprendre à considérer ce que nous savons à travers le modèle objet. Et vous allez vous rendre compte que la plupart du temps nous n'avons fait qu'effleurer les fonctionnalités du langage. Vous allez peut-être même demander grâce avant la fin de ce chapitre
clin.png
.

Je ne vais pas revenir sur ce que j'ai dit, pour afficher une chaîne, on passe par la fonction print.

Code : Python1
2
chaine = "Bonjour tout le monde !"
print(chaine)




Rien de nouveau ici. En revanche, on va un peu changer nos habitudes quand on désire afficher plusieurs variables.

Jusqu'ici, nous avons utilisé print en lui passant plusieurs paramètres. Ca marche, mais nous allons voir quelque chose légèrement plus flexible, qui d'ailleurs n'est pas seulement utile pour l'affichage.

Code : Python Console1
2
3
4
5
>>> prenom = "Paul"
>>> nom = "Dupont"
>>> age = 21
>>> print("Je m'appelle {0} {1} et j'ai {2} ans.".format(prenom, nom, age))
Je m'appelle Paul Dupont et j'ai 21 ans.




Mais ! C'est quoi ça ?


Question légitime. Voyons un peu
smile.png
.

Première syntaxe de la méthode format


Nous avons utilisé une méthode de la classe str (encore une) pour formater notre chaîne. De gauche à droite, nous avons :


  • une chaîne de caractères qui ne présente rien de particulier, sauf ces accolades entourant des nombres, d'abord 0, puis 1, puis 2 ;
  • nous appelons la méthode format de cette chaîne en lui passant en paramètre les variables à afficher, dans un ordre bien précis ;
  • quand Python exécute cette méthode, il va remplacer dans notre chaîne {0} par la première variable passée à la méthode format (soit le prénom), {1} par la deuxième variable... ainsi de suite.


Souvenez-vous qu'en programmation, on commence à compter à partir de 0.

Bien, mais on aurait pu faire exactement la même chose en passant plusieurs valeurs à print, non ?


Absolument. Mais rappelez-vous que cette fonctionnalité est bien plus puissante qu'un simple affichage, vous pouvez formater des chaînes de cette façon. Ici, nous avons directement affiché la chaîne formatée, mais nous aurions pu la stocker :

Code : Python Console1
2
>>> nouvelle_chaine = "Je m'appelle {0} {1} et j'ai {2} ans.".format(prenom, nom, age)
>>>




Pour faire la même chose sans utiliser format, on aurait dû concaténer des chaînes, ce que nous allons voir un peu plus loin, mais ça reste plus élégant.

Dans cet exemple, nous avons appelé les variables dans l'ordre où nous les placions dans format, mais ce n'est pas une obligation. Considérez cet exemple :

Code : Python Console1
2
3
4
5
6
7
>>> prenom = "Paul"
>>> nom = "Dupont"
>>> age = 21
>>> print( \
... "Je m'appelle {0} {1} ({3} {0} pour l'administration) et j'ai {2} ans." \
... .format(prenom, nom, age, nom.upper()))
Je m'appelle Paul Dupont (DUPONT Paul pour l'administration) et j'ai 21 ans.'




J'ai coupé notre instruction, plutôt longue, à l'aide du signe « \ » placé avant un saut de ligne, pour dire à Python que l'instruction se prolongeait au-dessous.

Si vous avez du mal à comprendre l'exemple, relisez l'instruction en remplaçant vous-même les nombres entre accolades par les variables (n'oubliez pas de compter à partir de 0).

Cette première syntaxe suffit la plupart du temps, mais n'est pas forcément intuitive quand on insère beaucoup de variables : on doit retenir leur position dans l'appel de format pour comprendre laquelle est affichée à tel endroit. Mais il existe une autre syntaxe.

Seconde syntaxe de la méthode format


On peut également nommer les variables que l'on va afficher, c'est souvent plus intuitif que d'utiliser leur indice. Voici un nouvel exemple :

Code : Python1
2
3
4
5
6
7
# formatage d'une adresse
adresse = """
{no_rue}, {nom_rue}
{code_postal} {nom_ville} ({pays})
""".format(no_rue=5, nom_rue="rue des Postes", code_postal=75003, \
nom_ville="Paris", pays="France")
print(adresse)




Code : Console
5, rue des Postes
75003 Paris (France)



Je pense que vous voyez assez précisément en quoi consiste cette deuxième syntaxe de format. Au lieu de donner des nombres entre accolades, on spécifie des noms de variable qui doivent correspondre à ceux entrés comme mot-clé dans la méthode format. Je ne m'attarderai pas davantage sur ce point, je pense qu'il est assez clair comme cela.

La concaténation de chaînes


Nous allons glisser très rapidement sur le concept de concaténation, assez intuitif d'ailleurs. On cherche à regrouper deux chaînes en une, en mettant la seconde à la suite de la première. Cela se fait le plus simplement du monde :

Code : Python Console 1
2
3
4
5
6
7
8
9
10
11
12
>>> prenom = "Paul"
>>> message = "Bonjour"
>>> chaine_complete = message + prenom # on utilise le symbole '+'
>>> # pour concaténer deux chaînes
... print(chaine_complete) # résultat :
BonjourPaul
>>> # pas encore parfait, il manque une espace
... # qu'à cela ne tienne !
... chaine_complete = message + " " + prenom
>>> print(chaine_complete) # résultat :
Bonjour Paul
>>>




C'est assez clair je pense. Le signe '+' utilisé pour ajouter des nombres est ici utilisé pour concaténer deux chaînes. Essayons à présent de concaténer des chaînes et des nombres :

Code : Python Console1
2
3
4
5
6
>>> age = 21
>>> message = "J'ai " + age + " ans."
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly
>>>




Python se fâche tout rouge ! Certains langages auraient accepté cette syntaxe sans sourciller mais Python n'aime pas ça du tout.

Au début de la première partie, nous avons dit que Python était un langage à typage dynamique, ce qui signifie qu'il identifie lui-même les types de données et que les variables peuvent changer de type au cours du programme. Mais Python est aussi un langage fortement typé, et cela veut dire que les types de données ne sont pas là pour faire joli, on ne peut les ignorer. Ainsi, vous voulez ici ajouter une chaîne à un entier et à une autre chaîne. Python ne comprend pas : est-ce que les chaînes contiennent des nombres que je dois convertir pour les ajouter à l'entier ou est-ce que l'entier doit être converti en chaîne puis concaténé avec les autres chaînes ? Python ne sait pas. Il ne le fera pas tout seul. Mais il s'avère de bonne volonté puisqu'il suffit de lui demander de convertir l'entier pour pouvoir le concaténer aux autres chaînes.

Code : Python Console1
2
3
4
5
>>> age = 21
>>> message = "J'ai " + str(age) + " ans."
>>> print(message)
J'ai 21 ans.
>>>




On appelle str pour convertir en une chaîne de caractères, comme nous avons appelé int pour convertir en entier. C'est le même mécanisme, sauf que convertir un entier en chaîne de caractères ne lèvera vraissemblablement aucune exception.

Le typage fort de Python est important. Il est un fondement de sa philosophie : j'ai tendance à considérer pour ma part qu'un langage faiblement typé (comme JavaScript qui aurait permis de concaténer ces deux chaînes et cet entier) crée des erreurs qui sont plus difficiles à repérer. Alors qu'ici, il nous suffit de convertir explicitement le type pour que Python sache ce qu'il doit faire.

Un petit extrait de la PEP 20 illustrera mes propos. Cette PEP (Python Enhancement Proposals : propositions d'amélioration de Python) reprend en phrases courtes et claires la philosophie de Python (c'est cadeau
smile.png
).

Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!
Explicit is better than implicit.



Courage ! On est presque à la fin. On jète un coup d'oeil au parcours et à la sélection de chaînes, et c'en sera fini de ce chapitre, riche en nouveautés... et en émotions
langue.png
.
Parcours et sélection de chaînes

Nous avons vu très rapidement dans la partie 1 un moyen de parcourir des chaînes. Nous allons en voir un second ici qui fonctionne par indice.

Parcours par indice


Vous devez vous en souvenir : j'ai dit qu'une chaîne de caractères était un ensemble constitué... de caractères
heureux.png
. En fait, une chaîne de caractères est elle-même constituée de chaînes de caractères mais qui ne se composent que d'un caractère.

Accéder aux caractères d'une chaîne


Nous allons apprendre à accéder aux lettres constituant une chaîne. Par exemple, nous souhaitons sélectionner la première lettre d'une chaîne.

Code : Python Console1
2
3
4
5
6
7
8
>>> chaine = "Salut les ZER0S !"
>>> chaine[0] # première lettre de la chaîne
'S'
>>> chaine[2] # troisième lettre de la chaîne
'l'
>>> chaine[-1] # dernière lettre de la chaîne
'!'
>>>




On précise entre crochets [] l'indice (la position du caractère auquel on souhaiterait accéder).

Rappelez-vous, on commence à compter à partir de 0. La première lettre est donc à l'indice 0, la deuxième à l'indice 1, la troisième à l'indice 2... On peut accéder aux lettres en partant de la fin en entrant un indice négatif. Quand vous entrez chaine[-1], vous accédez ainsi à la dernière lettre de la chaîne (enfin, au dernier caractère, qui n'est pas une lettre ici).

On peut obtenir la longueur de la chaîne (le nombre de caractères qu'elle contient) grâce à la fonction len.

Code : Python Console1
2
3
4
>>> chaine = "Salut"
>>> len(chaine)
5
>>>




Pourquoi ne pas avoir défini cette fonction comme une méthode de la classe str ? Pourquoi ne pourrait-on pas faire chaine.len() ?


En fait, c'est un peu le cas je vous montrerai bien plus loin. Mais, avant tout, str n'est qu'un exemple parmi d'autres d'ensembles (on en découvrira d'autres dans les prochains chapitres) et donc les développeurs de Python ont préféré créer une fonction qui travaillerait sur l'ensemble, plutôt qu'une méthode dans toutes ces classes.

Méthode de parcours par while


Eh bien vous en savez assez pour parcourir une chaîne grâce à la boucle while. Notez que dans la plupart des cas, on préférera parcourir un ensemble avec for, mais il est bien de savoir faire autrement, ça vous sera utile parfois.

Voici le code auquel vous pourriez arriver :

Code : Python1
2
3
4
5
chaine = "Salut"
i = 0 # on appelle notre indice 'i' par convention
while i<len(chaine):
print(chaine) # on affiche le caractère à chaque tour de boucle
i += 1




N'oubliez pas d'incrémenter i, sinon vous allez avoir quelques surprises
heureux.png
.

Si vous essayez d'accéder à un indice qui n'existe pas (par exemple 25 alors que votre chaîne ne fait que 20 de longueur), Python lèvera une exception de type IndexError.

Une petite dernière chose : vous ne pouvez changer les lettres de la chaîne en utilisant les indices :

Code : Python Console1
2
3
4
5
6
>>> mot = "lac"
>>> mot[0] = "b" # on veut remplacer 'l' par 'b'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>>




Python n'est pas content. Il ne veut pas que vous utilisiez les indices pour modifier des caractères de la chaîne. Pour ce faire, il va falloir utiliser la sélection.

Sélection de chaînes


Chouette ! On va faire du copier-coller ?
blink.gif



Euh... presque
langue.png
.

Nous allons voir comment sélectionner une partie de la chaîne.

Si je souhaite par exemple sélectionner les deux premières lettres de la chaîne :

Code : Python1
2
3
4
5
6
>>> presentation = "salut"
>>> presentation[0:2] # on sélectionne les deux premières lettres
'sa'
>>> presentation[2:len(presentation)] # on sélectionne la chaîne sauf les deux premières lettres
'lut'
>>>




La sélection consiste donc à extraire une partie de la chaîne. Cette opération retourne le morceau de la chaîne sélectionné (encore une fois sans modifier la chaîne d'origine).

Sachez que l'on peut sélectionner du début de la chaîne jusqu'à un indice, et d'un indice jusqu'à la fin de la chaîne, sans le préciser comme nous l'avons fait. Python comprend très bien si on le sous-entend :

Code : Python1
2
3
4
5
>>> presentation[:2] # du début jusqu'à la troisième lettre non comprise
'sa'
>>> presentation[2:] # de la troisième lettre (comprise) à la fin
'lut'
>>>




Maintenant, nous pouvons reprendre notre exemple de tout à l'heure pour constituer une nouvelle chaîne, en remplaçant une lettre par une autre :

Code : Python Console1
2
3
4
5
>>> mot = "lac"
>>> mot = "b" + mot[1:]
>>> print(mot)
bac
>>>




Voilà !
heureux.png


Ça reste assez peu intuitif non ?


Pour remplacer des lettres, ça paraît un peu lourd en effet. Et d'ailleurs on s'en sert assez rarement pour ça. Pour rechercher / remplacer, on a les méthodes count, find et replace dont je vous laisse le soin de comprendre le fonctionnement
clin.png
.

Aller, on peut passer au QCM, vous avez le droit à l'interpréteur pour celui-là
clin.png
.

Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!