Métamorphoses d'attributs de classe

Une courte note de la série "Vous avez été prévenu".

Passer des langages de programmation classiques à Python apporte beaucoup de surprises.
Lisez la documentation:
De manière générale, les variables d'instance sont pour les données propres à chaque instance et les variables de classe sont pour les attributs et les méthodes partagés par toutes les instances de la classe
Essayons de jouer

class Vessel: #class attribute vtype = "boat" #instance attribute def __init__(self, name): self.name = name #    def __str__(self): res= '>>' for a in inspect.getmembers( self): if not a[0].startswith("__"): res += f"{a[0]}={a[1]:<14}" for a in inspect.getmembers( self.__class__): if not a[0].startswith("__"): res += f"__class__.{a[0]}={a[1]:<14}" return res 


Créez deux objets, vérifiez les valeurs de tous les attributs:

 Iowa = Vessel("Iowa") Drum=Vessel("Drum") printAttr(Iowa, Drum) >>name=Iowa vtype=boat __class__.vtype=boat >>name=Drum vtype=boat __class__.vtype=boat 

Jusqu'à présent, comme prévu.

Essayons de changer vtype: cela peut être fait de deux façons, qui sont essentiellement juste une syntaxe différente de la même

 Vessel.vtype = "USS boat" printAttr(Iowa, Drum) >>name=Iowa vtype=USS boat __class__.vtype=USS boat >>name=Drum vtype=USS boat __class__.vtype=USS boat Iowa.__class__.vtype = 'USS WW2 Boat' printAttr(Iowa, Drum) >>name=Iowa vtype=USS WW2 Boat __class__.vtype=USS WW2 Boat >>name=Drum vtype=USS WW2 Boat __class__.vtype=USS WW2 Boat 

Et encore une fois, tout est en ordre.

Essayons maintenant de faire de même à travers l'attribut de l'objet.

 Drum.vtype = 'submarine' printAttr(Iowa, Drum) >>name=Iowa vtype=USS WW2 Boat __class__.vtype=USS WW2 Boat >>name=Drum vtype=submarine __class__.vtype=USS WW2 Boat 

Et voici la première surprise: malgré le fait que vtype est un attribut d'une classe, il devient soudainement un attribut d'un objet.

Vérifier:

 Vessel.vtype = "NAVY Museum" >>name=Iowa vtype=NAVY Museum __class__.vtype=NAVY Museum >>name=Drum vtype=submarine __class__.vtype=NAVY Museum 

Et si ...

  del Drum.vtype >>name=Iowa vtype=NAVY Museum __class__.vtype=NAVY Museum >>name=Drum vtype=NAVY Museum __class__.vtype=NAVY Museum 

Et encore un attribut de classe.

L'expression suivante ne passe plus

 del Drum.vtype printAttr(Iowa, Drum) del Drum.vtype AttributeError: vtype 

Et le dernier exemple émulant des substitutions de classe et supprimant l'attribut vtype.

 Drum.vtype = 'submarine' del Vessel.vtype printAttr(Iowa, Drum) >>name=Iowa >>name=Drum vtype=submarine 

Si vous commencez à gérer l'espace de noms, ce comportement devient compréhensible.
Cependant, pour les programmeurs qui travaillaient auparavant avec des langages normaux, cela semble au moins étrange. Et si nous parlons de grands projets qui sont soutenus par plusieurs générations de développeurs, cela peut se révéler être un échec des délais, etc.

Compte tenu du concept de Python selon lequel tout est ouvert à tous, pourquoi ne pas accéder aux attributs "cool" uniquement via __class__ ou son analogue. À mon avis, cela protégerait au moins en quelque sorte contre les surprises et me ferait réfléchir 10 fois avant d'attribuer quelque chose aux attributs de classe au niveau de l'objet.

Mise à jour: Text PrintAttr

 def printAttr(*o): for a in o: print(a) 

Source: https://habr.com/ru/post/fr427065/


All Articles