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.pi3.141592653589793La 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.hauteur100Comme 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.largeur200Liste 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')TrueCe 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 :
modules
packages
fonctions
classes
instances