J'essayais de trouver une bonne source qui explique pourquoi l'utilisation de global
est considérée comme une mauvaise pratique dans python (et dans la programmation en général). Quelqu'un peut-il m'indiquer un ou expliquer ici?
Cela n'a rien à voir avec Python; les variables globales sont mauvaises dans n'importe quel langage de programmation.
Cependant, les constantes globales ne sont pas théoriquement identiques aux variables globales ; les constantes globales sont parfaitement inoffensives. C'est juste que dans Python il n'y a pas de différence imposée, seulement par convention sont CONSTANTS_CAPITALIZED
et globals_are_not
.
La raison pour laquelle ils sont mauvais, c’est qu’ils permettent aux fonctions d’avoir des effets secondaires cachés (non évidents, surprenants, difficiles à détecter), ce qui entraîne une augmentation de la complexité, pouvant conduire à code Spaghetti .
Cependant, une utilisation rationnelle de l'état global est acceptable (de même que l'état local et la mutabilité) même en programmation fonctionnelle, que ce soit pour l'optimisation d'algorithme, la complexité réduite, la mise en cache et la mémorisation, ou l'aspect pratique des structures de portage provenant d'une base de code essentiellement impérative.
Dans l’ensemble, il est possible de répondre à votre question de différentes manières. Le mieux est donc de rechercher simplement "pourquoi les variables globales sont-elles mauvaises". Quelques exemples:
Si vous voulez aller plus loin et découvrir pourquoi les effets secondaires sont tous liés, et bien d’autres choses éclairantes, vous devriez apprendre la programmation fonctionnelle:
Oui, en théorie, les globaux (et "l'état" en général) sont diaboliques. En pratique, si vous examinez le répertoire packages de votre python, vous constaterez que la plupart des modules commencent par un ensemble de déclarations globales. De toute évidence, les gens n'ont aucun problème avec eux.
En particulier pour Python, la visibilité des globals est limitée à un module. Par conséquent, il n'y a pas de "vrais" globals qui affectent l'ensemble du programme, ce qui les rend moins dangereux. Autre point: il n’existe pas de const
, vous devez donc utiliser une constante pour obtenir une constante.
Dans ma pratique, s'il m'est arrivé de modifier un global dans une fonction, je le déclare toujours avec global
, même si cela n'est techniquement pas nécessaire, comme dans:
cache = {}
def foo(args):
global cache
cache[args] = ...
Cela facilite la traçabilité des manipulations des globals.
Selon un avis personnel sur le sujet, le fait d’utiliser des variables globales dans une logique de fonction signifie qu’un autre code peut modifier la logique et le résultat attendu de cette fonction, ce qui rendra le débogage très difficile (en particulier dans les grands projets) et rendra le test plus difficile. ainsi que.
De plus, si vous considérez que d'autres personnes lisent votre code (communauté open-source, collègues, etc.), elles auront du mal à comprendre où la variable globale est définie, où a été changé et à quoi s'attendre de cette variable globale par opposition à une fonction isolée que sa fonctionnalité peut être déterminée en lisant la définition de la fonction elle-même.
Je crois qu'un code propre et (presque) sans bug devrait avoir des fonctions aussi pures que possible (voir fonctions pures ). Une fonction pure est celle qui a les conditions suivantes:
Avoir des variables globales viole au moins l'un des éléments ci-dessus, sinon les deux, car un code externe peut probablement entraîner des résultats inattendus.
Une autre définition claire des fonctions pures: "Fonction pure est une fonction qui prend toutes ses entrées sous forme d'arguments explicites et produit tous ses résultats en tant que résultats explicites . " [1] . Avoir des variables globales viole l’idée de fonctions pures puisqu’une entrée et peut-être l’une des sorties (la variable globale) n’est pas explicitement donnée ou retournée.
De plus, si vous considérez les tests unitaires et le principe FIRST ( [~ # ~] f [~ # ~] , ast testez, [~ # ~] i [~ # ~] tests indépendants, [~ # ~] r [~ # ~] épatable, [~ # ~] s [~ # ~] elf-Validation et [~ # ~] t [~ # ~] immédiatement) violera probablement le principe des tests indépendants (ce qui signifie que les tests ne dépendent pas les uns des autres).
Avoir une variable globale (pas toujours), mais dans la plupart des cas (du moins de ce que j'ai vu jusqu'à présent), c'est préparer et transmettre les résultats à d'autres fonctions. Cela viole également ce principe. Si la variable globale a été utilisée de cette manière (c'est-à-dire que la variable globale utilisée dans la fonction X doit d'abord être définie dans une fonction Y), cela signifie que pour que la fonction de test unitaire X soit exécutée, vous devez d'abord exécuter la fonction de test/exécution Y.
D'autre part et comme d'autres personnes l'ont déjà mentionné, si la variable globale est utilisée comme variable "constante", cela peut être légèrement mieux, car le langage ne prend pas en charge les constantes. Cependant, je préfère toujours travailler avec des classes et avoir les "constantes" en tant que membre de la classe et ne pas utiliser de variable globale. Si vous avez un code dont deux classes différentes ont besoin pour partager une variable globale, vous devrez probablement refactoriser votre solution et rendre vos classes indépendantes.
Je ne crois pas que les globals ne devraient pas être utilisés. Mais s’ils sont utilisés, les auteurs devraient considérer certains principes (ceux mentionnés ci-dessus et peut-être d’autres principes et bonnes pratiques en matière de génie logiciel) pour obtenir un code plus propre et presque sans bugs.
Ils sont essentiels, l’écran étant un bon exemple. Toutefois, dans un environnement multithread ou impliquant de nombreux développeurs, la question qui se pose est souvent la suivante: qui l'a (à tort) définie ou effacée? Selon l'architecture, l'analyse peut être coûteuse et souvent nécessaire. Bien que la lecture de la variable globale puisse être correcte, l’écriture doit être contrôlée, par exemple, par un seul thread ou une classe threadsafe. Par conséquent, les coûts globaux résultent de la crainte de coûts de développement élevés possibles du fait des conséquences pour lesquelles ils sont considérés comme pervers. Par conséquent, en règle générale, il est judicieux de limiter le nombre de vars globaux.