Explication de la leçon
Après cette leçon, tu seras capable de :
__init__.Un attribut d'instance est stocké sur un objet particulier, généralement affecté dans __init__ sous la forme self.name = name. Un attribut de classe est écrit dans le corps de la classe et est partagé comme valeur par défaut par chaque instance de cette classe :
class Worker:
region = "eu"
def __init__(self, name):
self.name = nameWorker.region lit le paramètre de classe. worker.region le lit également jusqu'à ce que cet objet particulier possède son propre attribut region. Si tu affectes worker.region = "us", cet objet masque désormais le paramètre de classe ; cela ne met pas à jour les autres workers.
Pour une configuration véritablement partagée, mets à jour Worker.region (la classe), et non une seule instance. Pour l'état propre à chaque objet tel que le nom d'un worker, ses tentatives ou son historique d'événements, utilise self.attribute dans __init__.
Piège important lié à l'état modifiable : une liste définie dans le corps de la classe peut être partagée par toutes les instances. Si chaque instance a besoin de sa propre liste, crée self.events = [] dans le constructeur.
class ApiClient:
scheme = "https"
def __init__(self, service):
self.service = service
first = ApiClient("users")
second = ApiClient("billing")
print(f"{first.service}: {first.scheme}")
print(f"{second.service}: {second.scheme}")Sortie :
users: https
billing: httpsLes deux objets lisent le même paramètre de classe tout en conservant leurs propres noms de service.
class Job:
mode = "safe"
first = Job()
second = Job()
Job.mode = "fast"
print(first.mode)
print(second.mode)Sortie :
fast
fastAucune instance ne définit son propre mode, donc les deux lisent toujours l'attribut de classe.
class Storage:
tier = "standard"
primary = Storage()
backup = Storage()
primary.tier = "premium"
print(primary.tier)
print(backup.tier)
print(Storage.tier)Sortie :
premium
standard
standardprimary.tier est devenu un attribut d'instance ; la valeur par défaut partagée de la classe est restée inchangée.
class Monitor:
def __init__(self, name):
self.name = name
self.events = []
def record(self, event):
self.events.append(event)
api = Monitor("api")
queue = Monitor("queue")
api.record("started")
print(api.events)
print(queue.events)Sortie :
['started']
[]Chaque appel de constructeur crée une nouvelle liste pour un moniteur donné.
| Situation | Où affecter |
|---|---|
| Valeur par défaut ou paramètre partagé | Dans le corps de la classe : mode = "safe" |
| Modifier un paramètre partagé | Worker.mode = "fast" |
| État par objet | Dans __init__ : self.name = name |
| Remplacer une valeur par défaut partagée pour une instance | worker.mode = "custom" |
| Liste modifiable par objet | Dans __init__ : self.events = [] |
obj.setting = value ne modifie pas ClassName.setting ; cela crée ou met à jour un attribut d'instance.self.name dans le corps de la classe n'est pas ainsi que fonctionne l'initialisation d'instance ; utilise __init__.