Objets et méthodes

Avant d’aller plus loin dans les interactions avec Python, j’aimerais que l’on prenne un peu de temps pour regarder de plus près la structure des données en Python.

Objets

Python est ce que l’on appelle un langage orienté objet (ou simplement langage objet). C’est-à-dire que toutes les valeurs que l’on manipule sont des objets : les entiers, les flottants ou les chaînes de caractères sont des objets.

Les objets sont définis comme des entités sur lesquels il est possible d’exécuter des actions (des opérations). Ils répondent ainsi à une interface qui définit quelles actions sont disponibles pour quels objets, c’est cette interface qu’on appelle le type.

Qu’est-ce que cela apporte ? C’est une manière de concevoir la structure d’un programme, de modéliser les interactions entre les valeurs. Il s’agit de définir les valeurs non pas selon ce qu’elles contiennent (des nombres, du texte) mais selon leur comportement : pouvoir être additionnées, pouvoir être affichées à l’écran, etc.

Méthodes

Les actions sur les objets sont plus généralement appelées des méthodes.

Elles sont très similaires aux fonctions, si ce n’est qu’elles appartiennent à un type et donc s’appliquent sur des objets en particulier (sur les objets de ce type).

Pour appeler une méthode sur une valeur, on fait suivre cette valeur d’un point puis du nom de la méthode, et enfin d’une paire de parenthèses comme pour les appels de fonction. On récupère de la même manière la valeur de retour de la méthode lors de l’évaluation de l’expression.

Par exemple la méthode strip du type str permet de renvoyer la chaîne de caractères en retirant les espaces présents au début et à la fin.

>>> '   hello '.strip()
'hello'

Pour que l’expression ait un sens, il faut bien sûr que la méthode existe pour cet objet. On obtient une erreur dans le cas contraire.

>>> 'hello'.toto()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'toto'

Méthodes des chaînes de caractères

Les chaînes de caractères possèdent d’autres méthodes utiles dont voici un bref aperçu. Nous en découvrirons encore bien d’autres dans la suite de ce cours.

strip

La méthode strip vue précédemment retire les espaces aux extrémités de la chaîne, mais n’affecte pas ceux qui se trouvent au milieu.

>>> ' hello   world '.strip()
'hello   world'

Il est possible d’appliquer la méthode sur une variable si celle-ci est assignée à une chaîne de caractères. Ou sur toute autre expression s’évaluant comme une chaîne de caractères, des parenthèses pouvant alors être nécessaires pour changer la priorité de l’opération.

>>> text = ' hello   world '
>>> text.strip()
'hello   world'
>>> input().strip()
  coucou
'coucou'
>>> (' to' * 3).strip()
'to to to'

Cette méthode, tout comme les autres qui suivent, renvoie une nouvelle chaîne de caractères modifiée. Elle n’affecte jamais directement la chaîne sur laquelle elle est appliquée.

>>> text.strip()
'hello   world'
>>> text
' hello   world '
capitalize et title

capitalize est une méthode qui permet de passer en majuscule le premier caractère de la chaîne (si c’est une lettre) et en minuscules tous les autres.

>>> 'coucou'.capitalize()
'Coucou'
>>> 'COUCOU'.capitalize()
'Coucou'

Semblable à capitalize, title effectue ce traitement sur tous les mots de la chaîne de caractères.

>>> 'bonjour à tous'.capitalize()
'Bonjour à tous'
>>> 'bonjour à tous'.title()
'Bonjour À Tous'
upper et lower

Il s’agit ici de passer la chaîne entière en majuscules ou en minuscules.

>>> 'CoUcOu'.upper()
'COUCOU'
>>> 'CoUcOu'.lower()
'coucou'
index

La méthode index permet de trouver un caractère dans la chaîne et d’en renvoyer la position. Il s’agit donc du comportement réciproque de l’opérateur [ ].

>>> text = 'abcdef'
>>> text.index('d')
3
>>> text[3]
'd'

À noter que si le caractère est présent plusieurs fois dans la chaîne, c’est la première position trouvée qui est renvoyée.

>>> 'abcabc'.index('b')
1

Et une erreur survient si le caractère n’est pas trouvé.

>>> 'abcdef'.index('g')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: substring not found

Attributs

Les objets sont caractérisés par leur type et les méthodes qui lui sont applicables, mais ce n’est pas tout. Chaque objet a une existence propre, qui le différencie des autres objets du même type, et des données annexes peuvent lui être associées.
Ces données annexes sont autant de valeurs qui peuvent décrire l’état interne des objets. On les appelle des attributs.

Ils sont peu utilisés sur les objets que nous manipulons jusqu’ici (nombres et chaînes de caractères) car ces objets correspondent à de la donnée brute et n’ont pas besoin de valeurs annexes.
Leur utilité peut alors ne pas sembler évidente pour le moment, mais elle le deviendra quand on manipulera des objets plus complexes, composés de différentes données.

Il n’empêche que nos objets de base possèdent tout de même quelques attributs. Par exemple, chaque objet Python est pourvu d’un attribut __class__ (faites bien attention aux deux underscores de chaque côté) qui permet d’accéder à son type.

>>> 'hello'.__class__
<class 'str'>
>>> 1.4.__class__
<class 'float'>

Vous découvrez ainsi la syntaxe pour accéder à un attribut d’un objet : on fait suivre l’objet d’un point puis du nom de l’attribut. C’est donc similaire aux méthodes, qui fonctionnent sur le même principe.

On notera cependant une petite différence pour les nombres entiers : comme le point y a déjà une signification (précéder une potentielle partie décimale) il ne peut pas être utilisé tel quel pour accéder aux attributs.
On ne peut ainsi pas écrire 42.__class__ qui ne serait pas compris par Python, il faut alors entourer le nombre de parenthèses pour lever toute ambigüité.

>>> 42.__class__
  File "<stdin>", line 1
    42.__class__
       ^
SyntaxError: invalid syntax
>>> (42).__class__
<class 'int'>

Cette exception ne s’applique bien sûr qu’aux nombres littéraux, et pas aux variables qui référencent des nombres qui n’ont aucun problème d’ambigüité à ce niveau.

>>> x = 42
>>> x.__class__
<class 'int'>

Les nombres entiers possèdent aussi deux attributs numerator (numérateur) et denominator (dénominateur) qui leur permettent d’être vus comme des fractions (et donc d’être utilisés dans un contexte où une fraction serait attendue, nous découvrirons ça plus tard). Comme il s’agit de nombres entiers, le dénominateur sera toujours de 1.

>>> x.numerator
42
>>> x.denominator
1