Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Licence CC BY-NC-ND Thierry Parmentelat & Arnaud Legout Inria - UCA

Compléments - niveau basique

La notation . et les attributs

La notation module.variable que nous avons vue dans la vidéo est un cas particulier de la notion d’attribut, qui permet d’étendre un objet, ou si on préfère de lui accrocher des données.

Nous avons déjà rencontré ceci de nombreuses fois à présent, c’est exactement le même mécanisme d’attribut qui est utilisé pour les méthodes ; pour le système d’attribut il n’y a pas de différence entre module.variable, module.fonction, objet.methode, etc.

Nous verrons très bientôt que ce mécanisme est massivement utilisé également dans les instances de classe.

Les fonctions de gestion des attributs

Pour accéder programmativement aux attributs d’un objet, on dispose des 3 fonctions built-in getattr, setattr, et hasattr, que nous allons illustrer tout de suite.

Lire un attribut

import math
# nous savons lire un attribut comme ceci 
# qui lit l'attribut de nom 'pi' dans le module math
math.pi
3.141592653589793

La fonction built-in getattr permet de lire un attribut programmativement :

# si on part d'une chaîne qui désigne le nom de l'attribut
# la formule équivalente est alors
getattr(math, 'pi')
3.141592653589793
# on peut utiliser les attributs avec la plupart des objets
# ici nous allons le faire sur une fonction
def foo(): 
    "une fonction vide"
    pass

# on a déjà vu certains attributs des fonctions
print(f"nom={foo.__name__}, docstring=`{foo.__doc__}`")
nom=foo, docstring=`une fonction vide`
# on peut préciser une valeur par défaut pour le cas où l'attribut
# n'existe pas
getattr(foo, "attribut_inexistant", 'valeur_par_defaut')
'valeur_par_defaut'

Écrire un attribut

# on peut ajouter un attribut arbitraire (toujours sur l'objet fonction)
foo.hauteur = 100

foo.hauteur
100

Comme pour la lecture on peut écrire un attribut programmativement avec la fonction built-in setattr :

# écrire un attribut avec setattr
setattr(foo, "largeur", 200)

# on peut bien sûr le lire indifféremment
# directement comme ici, ou avec getattr
foo.largeur
200

Liste des attributs

La fonction built-in hasattr permet de savoir si un objet possède ou pas un attribut :

# pour savoir si un attribut existe
hasattr(math, 'pi')
True

Ce qui peut aussi être retrouvé autrement, avec la fonction built-in vars :

vars(foo)
{'hauteur': 100, 'largeur': 200}

Sur quels objets

Il n’est pas possible d’ajouter des attributs sur les types de base, car ce sont des classes immuables :

for builtin_type in (int, str, float, complex, tuple, dict, set, frozenset):
    obj = builtin_type()
    try: 
        obj.foo = 'bar'
    except AttributeError as e: 
        print(f"{builtin_type.__name__:>10} → exception {type(e)} - {e}")
       int → exception <class 'AttributeError'> - 'int' object has no attribute 'foo'
       str → exception <class 'AttributeError'> - 'str' object has no attribute 'foo'
     float → exception <class 'AttributeError'> - 'float' object has no attribute 'foo'
   complex → exception <class 'AttributeError'> - 'complex' object has no attribute 'foo'
     tuple → exception <class 'AttributeError'> - 'tuple' object has no attribute 'foo'
      dict → exception <class 'AttributeError'> - 'dict' object has no attribute 'foo'
       set → exception <class 'AttributeError'> - 'set' object has no attribute 'foo'
 frozenset → exception <class 'AttributeError'> - 'frozenset' object has no attribute 'foo'

C’est par contre possible sur virtuellement tout le reste, et notamment là où c’est très utile, c’est-à-dire pour ce qui nous concerne sur les :