J'ai des classes Python, dont je n'ai besoin que d'une seule instance à l'exécution, il serait donc suffisant d'avoir les attributs une seule fois par classe et non par instance. S'il y a plus d'une instance (ce qui ne se produira pas), toutes les instances doivent avoir la même configuration. Je me demande laquelle des options suivantes serait la meilleure ou la plus "idiomatique" Python.
Variables de classe:
class MyController(Controller):
path = "something/"
children = [AController, BController]
def action(self, request):
pass
Variables d'instance:
class MyController(Controller):
def __init__(self):
self.path = "something/"
self.children = [AController, BController]
def action(self, request):
pass
Réponses:
Si vous n'avez de toute façon qu'une seule instance, il est préférable de rendre toutes les variables par instance, simplement parce qu'elles seront accédées (un peu) plus rapidement (un niveau de "recherche" de moins en raison de "l'héritage" d'une classe à l'autre), et il n'y a pas d'inconvénients à peser contre ce petit avantage.
la source
python -mtimeit
- mais je viens de le faire en python3.4 Je note que l'accès à uneint
variable de classe est en fait environ 5 à 11 nanosecondes plus rapide que la même variable d'instance sur mon ancien poste de travail - je ne sais pas quoi codepath le rend ainsi.Reprenant les conseils de Mike et Alex et ajoutant ma propre couleur ...
L'utilisation d'attributs d'instance est typique ... le Python le plus idiomatique. Les attributs de classe ne sont pas utilisés autant, car leurs cas d'utilisation sont spécifiques. Il en va de même pour les méthodes statiques et de classe par rapport aux méthodes «normales». Ce sont des constructions spéciales traitant des cas d'utilisation spécifiques, sinon c'est du code créé par un programmeur aberrant qui veut montrer qu'il connaît un coin obscur de la programmation Python.
Alex mentionne dans sa réponse que l'accès sera (un peu) plus rapide en raison d'un niveau de recherche en moins ... laissez-moi clarifier davantage pour ceux qui ne savent pas encore comment cela fonctionne. Il est très similaire à l'accès aux variables - dont l'ordre de recherche est:
Pour l'accès aux attributs, l'ordre est:
Les deux techniques fonctionnent de manière «à l'envers», ce qui signifie que les objets les plus locaux sont vérifiés en premier, puis les couches externes sont vérifiées successivement.
Dans votre exemple ci-dessus, disons que vous recherchez l'
path
attribut. Lorsqu'il rencontre une référence telle que "self.path
", Python examinera d'abord les attributs de l'instance pour une correspondance. Lorsque cela échoue, il vérifie la classe à partir de laquelle l'objet a été instancié. Enfin, il recherchera les classes de base. Comme Alex l'a déclaré, si votre attribut est trouvé dans l'instance, il n'a pas besoin de chercher ailleurs, d'où votre petit gain de temps.Cependant, si vous insistez sur les attributs de classe, vous avez besoin de cette recherche supplémentaire. Ou , votre autre alternative est de faire référence à l'objet via la classe au lieu de l'instance, par exemple
MyController.path
au lieu deself.path
. C'est une recherche directe qui contournera la recherche différée, mais comme Alex le mentionne ci-dessous, c'est une variable globale, donc vous perdez ce bit que vous pensiez que vous alliez enregistrer (à moins que vous ne créiez une référence locale au nom de la classe [global] ).L'essentiel est que vous devez utiliser les attributs d'instance la plupart du temps. Cependant, il y aura des occasions où un attribut de classe est le bon outil pour le travail. Le code utilisant les deux en même temps nécessitera le plus de diligence, car l'utilisation
self
ne vous donnera que l'objet d'attribut d'instance et l' accès des ombres à l'attribut de classe du même nom. Dans ce cas, vous devez utiliser l'accès à l'attribut par le nom de classe afin de le référencer.la source
MyController
est recherché dans les globaux, donc le coût total est plus élevé que celuiself.path
où sepath
trouve une variable d'instance (puisqueself
est local à la méthode == recherche ultra-rapide).En cas de doute, vous souhaitez probablement un attribut d'instance.
Les attributs de classe sont mieux réservés aux cas spéciaux où ils ont un sens. Le seul cas d'utilisation très courant concerne les méthodes. Il n'est pas rare d'utiliser des attributs de classe pour les constantes en lecture seule que les instances ont besoin de connaître (bien que le seul avantage à cela soit si vous souhaitez également un accès depuis l' extérieur de la classe), mais vous devez certainement être prudent lorsque vous stockez un état dans ces dernières. , ce qui est rarement ce que vous voulez. Même si vous n'avez qu'une seule instance, vous devez écrire la classe comme vous le feriez pour n'importe quelle autre, ce qui signifie généralement utiliser des attributs d'instance.
la source
avoid global variables
et leur définition est, que les variables globales sont aussi des variables qui sont déclarées comme attributs de classe. Cependant, le propre guide de style de Python ( PEP-8 ) devrait être le premier endroit où aller pour des questions de ce type. Ensuite, votre propre esprit devrait être l'outil de choix (bien sûr, vous pouvez également obtenir des idées de Google, par exemple).Même question à Performance d'accès aux variables de classe en Python - le code ici adapté de @Edward Loper
Les variables locales sont les plus rapides d'accès, à peu près liées aux variables de module, suivies des variables de classe, suivies des variables d'instance.
Il y a 4 portées auxquelles vous pouvez accéder aux variables:
Le test:
Le résultat:
la source