Je lisais une question sur l'instruction Python globale ( "portée Python" ) et je me souvenais de la fréquence à laquelle j'ai utilisé cette déclaration quand j'étais un débutant Python (j'ai utilisé global ) ) et comment, de nos jours, des années plus tard, je ne l'utilise plus du tout, je le considère même un peu "anti-Pythonique".
Utilisez-vous cette instruction dans Python? Votre utilisation en a-t-elle changé avec le temps?
J'utilise "global" dans un contexte comme celui-ci:
_cached_result = None
def myComputationallyExpensiveFunction():
global _cached_result
if _cached_result:
return _cached_result
# ... figure out result
_cached_result = result
return result
J'utilise "global" parce que cela a du sens et est clair pour le lecteur de la fonction de ce qui se passe. Je sais également qu'il existe ce modèle, qui est équivalent, mais impose une charge cognitive plus importante au lecteur:
def myComputationallyExpensiveFunction():
if myComputationallyExpensiveFunction.cache:
return myComputationallyExpensiveFunction.cache
# ... figure out result
myComputationallyExpensiveFunction.cache = result
return result
myComputationallyExpensiveFunction.cache = None
Je n'ai jamais eu une utilisation légitime de la déclaration dans un code de production au cours de mes 3+ années d'utilisation professionnelle de Python et plus de cinq ans en tant que Python Tout état que je dois changer réside dans des classes ou, s'il y a un état "global", il se trouve dans une structure partagée comme un cache global.
Je l'ai utilisé dans des situations où une fonction crée ou définit des variables qui seront utilisées globalement. Voici quelques exemples:
discretes = 0
def use_discretes():
#this global statement is a message to the parser to refer
#to the globally defined identifier "discretes"
global discretes
if using_real_hardware():
discretes = 1
...
ou
file1.py:
def setup():
global DISP1, DISP2, DISP3
DISP1 = grab_handle('display_1')
DISP2 = grab_handle('display_2')
DISP3 = grab_handle('display_3')
...
file2.py:
import file1
file1.setup()
#file1.DISP1 DOES NOT EXIST until after setup() is called.
file1.DISP1.resolution = 1024, 768
Je l'utilise pour les options globales avec des scripts de ligne de commande et 'optparse':
my main () analyse les arguments et les transmet à n'importe quelle fonction qui fait le travail du script ... mais écrit les options fournies dans un dictionnaire global 'opts'.
Les options de script shell tordent souvent le comportement "feuille", et il n'est pas pratique (et inutile) de faire passer le dictionnaire "opts" dans chaque liste d'arguments.
Les objets sont le moyen préféré d'avoir un état non local, donc global est rarement nécessaire. Je ne pense pas non plus que le prochain modificateur non local sera largement utilisé, je pense qu'il est principalement là pour que les lispers cessent de se plaindre :-)
Je l'évite et nous avons même une règle pylint qui l'interdit dans notre code de production. En fait, je pense que cela ne devrait même pas exister du tout.
Il peut être utile dans les threads pour partager l'état (avec des mécanismes de verrouillage autour).
Cependant, je l'utilise rarement, voire jamais.
Je l'ai utilisé dans des scripts rapides à usage unique pour automatiser certaines tâches ponctuelles. Tout ce qui est plus grand que cela, ou qui doit être réutilisé, et je trouverai un moyen plus élégant.
Rarement. Je n'ai pas encore trouvé d'utilisation.
Une fois ou deux. Mais c'était toujours un bon point de départ pour refactoriser.
Si je peux l'éviter, non. Et, à ma connaissance, il y a toujours moyen de l'éviter. Mais je ne dis pas non plus que c'est totalement inutile