>>> b.test is a.test
False
>>> a.test is a.test
False
Les méthodes sont créées à la volée chaque fois que vous les consultez. L'objet fonction (qui est toujours le même objet) implémente le protocole des descripteurs et son __get__
crée l'objet méthode liée. Normalement, aucun deux méthodes liées ne seraient le même objet.
>>> id(a.test) == id(b.test)
True
>>> a.test is b.test
False
Cet exemple est trompeur. Le résultat du premier est seulement True
par coïncidence. a.test
crée une méthode liée et elle est nettoyée par le ramasse-miettes après le calcul de id(a.test)
car il n'y a pas de références à cette méthode. (Notez que vous avez cité la documentation disant qu'un id est "unique et constant pour cet objet pendant sa durée de vie" (soulignement ajouté).) b.test
happen a le même id que la méthode liée que vous aviez avant et c'est autorisé car aucun autre objet n'a le même id maintenant.
Notez que vous devriez rarement utiliser is
et encore moins utiliser id
. id(foo) == id(bar)
est toujours faux.
Concernant votre nouvel exemple, espérons que vous compreniez maintenant ce qu'il fait :
>>> new_improved_test_method = lambda: None
>>> a.test = new_improved_test_method
>>> a.test is a.test
True
Dans ce cas, nous ne créons pas des méthodes à la volée à partir de fonctions sur la classe en liant automatiquement self et renvoyant des objets méthode liée. Dans ce cas, vous stockez simplement une fonction en tant qu'attribut d'instance. Rien de spécial ne se produit lors de la recherche (les descripteurs ne sont appelés que lorsque vous recherchez un attribut de classe), donc à chaque fois que vous recherchez l'attribut, vous obtenez l'objet original que vous avez stocké.