Python / Objets et variables

En Python, un objet représente des données avec une valeur et des opérations possibles ; une variable est un nom lié à cet objet. x = 100 lie x à un entier, puis une nouvelle affectation change l’objet désigné. L’affectation ne copie pas automatiquement les objets : plusieurs noms peuvent donc partager la même liste.

Noms, objets et types

Le modèle de données Python attribue aux objets une identité, un type et une valeur. Le type détermine les opérations et propriétés ; l’identité reste stable pendant la vie de l’objet. La possibilité de modifier la valeur dépend du type. Imaginer une variable comme une boîte de type fixe explique mal les nouvelles liaisons et le partage.

Les exemples utilisent Python 3 et la bibliothèque standard. Leurs sorties ont été vérifiées avec Python 3.12.14. Enregistrez chaque code complet en UTF-8 dans objects_demo.py et lancez python objects_demo.py dans un terminal, ou python3 selon l’environnement. Remplacez le contenu pour chaque exemple indépendant.

value = 100
print(value, type(value).__name__)
value = "hello"
print(value, type(value).__name__)
100 int
hello str

value désigne d’abord un int, puis un str. L’entier 100 lui-même n’a pas changé de type. Une affectation évalue l’expression de droite et lie le résultat au nom de gauche. type(value) examine le type de l’objet actuellement désigné.

Partager une liste ou réaffecter un nom

second = first ne crée pas de copie : les deux noms désignent la même liste. Comparez la modification de l’objet partagé et la nouvelle liaison d’un seul nom :

first = [1, 2]
second = first
second.append(3)
print(first)
print(second)
print(first is second)
first = [0]
print(first)
print(second)
print(first is second)
[1, 2, 3]
[1, 2, 3]
True
[0]
[1, 2, 3]
False

append modifie la liste partagée, donc first montre aussi le 3 ajouté. En revanche, first = [0] lie uniquement first à une nouvelle liste. second garde l’ancienne référence. Il faut distinguer la liaison d’un nom du contenu de l’objet désigné.

Opération Signification Effet sur l’autre nom
second = first Ajouter un nom pour le même objet Les deux observent les mutations
second.append(3) Modifier la liste La lecture de la même liste reflète le changement
first = [0] Lier first à un autre objet second conserve sa liaison

Objets immuables et +=

Les entiers, chaînes et tuples sont immuables ; les listes et dictionnaires sont mutables. L’immuabilité concerne l’objet lui-même et n’interdit pas d’affecter une autre valeur à son nom.

first = 10
second = first
first += 1
print(first)
print(second)
11
10

L’entier 10 n’est pas transformé en 11. first est lié au résultat de l’addition, tandis que second désigne toujours 10. Avec une liste, la même syntaxe += peut modifier l’objet existant ; ne généralisez pas son comportement à tous les types. Les références contenues dans un tuple ne peuvent pas être remplacées, mais le contenu d’une liste qu’il contient peut évoluer.

Choisir la profondeur de copie

copy() d’une liste crée une nouvelle liste extérieure : c’est une copie superficielle. Les objets imbriqués restent partagés. Comparez-la à copy.deepcopy() sur les mêmes données initiales :

from copy import deepcopy

original = [[1], [2]]
shallow = original.copy()
deep = deepcopy(original)
shallow[0].append(9)
shallow.append([3])
print(original)
print(shallow)
print(deep)
print(original is shallow)
print(original[0] is shallow[0])
[[1, 9], [2]]
[[1, 9], [2], [3]]
[[1], [2]]
False
True

Ajouter 9 à la liste interne via shallow apparaît aussi dans original. Ajouter [3] à la liste extérieure de shallow n’allonge pas original. deep conserve une copie indépendante des données imbriquées initiales. Déterminez d’abord si le partage est voulu et copiez seulement la portée nécessaire. La copie profonde a un coût et ne duplique pas les fichiers ou sockets comme de simples données.

Égalité et identité : == et is

Pour les listes natives, == compare le contenu et is vérifie qu’il s’agit exactement du même objet. Ces listes ont été créées séparément malgré leur contenu égal :

left = [1, 2]
right = [1, 2]
alias = left
print(left == right)
print(left is right)
print(left is alias)
print(id(left) == id(alias))
missing = None
print(missing is None)
True
False
True
True
True

Employez les opérateurs de comparaison selon leur rôle. id() fournit un entier représentant l’identité ; sa valeur concrète peut changer entre exécutions et n’est pas une adresse mémoire dans toutes les implémentations Python. Ne comparez pas nombres et chaînes avec is en comptant sur la réutilisation d’objets. Utilisez == pour les valeurs et is None pour tester None.

del supprime la liaison d’un nom

del est une instruction, pas une fonction. del first retire la liaison du nom. Un objet reste utilisable par un autre nom qui le désigne encore :

first = [1, 2]
second = first
del first
print(second)
try:
    print(first)
except NameError:
    print("first: NameError")
try:
    del unknown_name
except NameError:
    print("unknown_name: NameError")
[1, 2]
first: NameError
unknown_name: NameError

second affiche toujours la liste, mais lire first lève NameError. Supprimer un nom inconnu produit aussi NameError. Selon sa cible, l’instruction del peut supprimer un élément ou un attribut ; elle ne supprime donc pas toujours un nom. Retirer une liaison ne garantit pas une destruction immédiate de l’objet ou la libération de sa mémoire. Fermez les fichiers avec with ou close plutôt qu’en comptant sur del.

Noms valides et lisibles

Avec les caractères latins simples, commencez par une lettre ou un soulignement ; les chiffres sont permis ensuite. Espaces et traits d’union sont interdits, et la casse compte. Python admet également certains caractères Unicode, les noms ne sont donc pas limités aux lettres anglaises.

import keyword

for name in ["user_name", "2name", "class", "first-name", "café", "match"]:
    valid = name.isidentifier() and not keyword.iskeyword(name)
    print(name, valid)
print("match soft keyword:", keyword.issoftkeyword("match"))
user_name True
2name False
class False
first-name False
café True
match True
match soft keyword: True

isidentifier() accepte la forme de class ; vérifiez donc aussi keyword.iskeyword(). Ici, match est un mot-clé contextuel, pas un mot réservé dans tous les contextes. Consultez la grammaire des identifiants et mots-clés. Les listes peuvent changer selon la version : utilisez le module keyword de votre interpréteur.

Même valides, list ou str peuvent masquer des noms natifs et compliquer leur utilisation. Préférez des noms exprimant le rôle, comme user_name ou item_count. En cas de NameError, vérifiez la casse, l’affectation préalable et la portée où le nom est disponible.