Initialisation de variables globales à l'aide de décorateurs Python

introduction

Quand je regardais le dépôt pip sur github, j'utilisais un décorateur intéressant, donc je vais le partager.

TL;DR --Le décorateur peut être utilisé non seulement pour modifier la fonction, mais aussi pour ** exécuter la fonction **.

Valeur de la variable globale lors de l'importation

Tout d'abord, quel type de valeur prend la variable globale lors de l'importation du package suivant? Les deux fonctions spam et ʻegg sont des fonctions uniquement pour mettre à jour la variable globale global_variable`.

mypackage/__init__.py


GLOBAL_VARIABLE = 0

def spam():
    global_variable = 1
    globals().update(locals())

def egg():
    global global_variable
    global_variable = 2

main.py


import mypackage
if __name__ == "__main__":
    print(mypackage.global_variable)

La valeur de global_variable n'a pas changé depuis sa déclaration, car nous ne faisons que définir la fonction et non l'exécuter. Bien entendu, le résultat de l'exécution est le suivant.

$python3 main.py
0

Alors que se passe-t-il si vous essayez d'appeler la fonction à la fin de mypackage / __ init __. Py?

mypackage/__init__.py


GLOBAL_VARIABLE = 0

def spam():
    global_variable = 1
    globals().update(locals())

def egg():
    global global_variable
    global_variable = 2

spam()
egg()

Dans ce cas, la fonction est appelée et la valeur de «global_variable» est écrasée à la fois dans «spam» et «egg», le résultat de l'exécution est donc le suivant.

$python3 main.py
2

Cependant, avec cette méthode, si le nombre de fonctions que vous souhaitez exécuter augmente, vous devez écrire le code pour appeler autant, ce qui est gênant. C'est là que le ** décorateur ** entre en jeu.

Exécuter la fonction à l'intérieur du décorateur

Voici le problème principal. Jetons un coup d'œil au code. Considérez la fonction suivante call_aside.

mypackage/__init__.py


global_variable = 0

def call_aside(f, *args, **kwargs):
    f(*args, **kwargs)
    return f

@call_aside
def spam():
    global_variable = 1
    globals().update(locals())

@call_aside
def egg():
    global global_variable
    global_variable = 2

main.py


import mypackage
if __name__ == "__main__":
    print(mypackage.global_variable)

Quel est le résultat de l'exécution

$python3 main.py
2

On dirait! Au début, je n'en comprenais pas la raison, j'étais donc assez inquiète. Cependant, le mécanisme est simple une fois que vous l'avez compris. En se concentrant sur la fonction call_aside,

def call_aside(f, *args, **kwargs):
    f(*args, **kwargs) # <- execute f
    return f

Et ainsi de suite, la fonction est appelée en interne. Par conséquent, juste en modifiant avec call_aside, spam et ʻegg sont exécutés lorsque mypackage est importé, donc la valeur de global_variable` a changé comme indiqué ci-dessus. Dans ce cas, même si le nombre de fonctions que vous souhaitez exécuter au moment de l'importation augmente, il vous suffit de le décorer: tada:

Supplément

Lors de l'examen des décorateurs Python, beaucoup expliquent les décorateurs qui ** utilisent des décorateurs pour "ajouter un traitement avant et après une fonction" et "renvoyer des fonctions avec un traitement ajouté avant et après" **. Je pense.

def decorator(f):
  def wrapper(*args, **kwargs):  
    print("Prétraitement")
    f(*args, **kwargs)
    print("Post-traitement")
  return wrapper

De cette manière, la fonction wrapper est uniquement définie et non exécutée. Même si vous décorez une fonction avec ce décorateur, il n'aura aucun effet tel que la mise à jour de la valeur de la variable globale jusqu'à ce que vous appeliez la fonction décorée.

référence

pypa/pip/blob/master/src/pip/_vendor/pkg_resources/__init__.py

finalement

Si vous pouvez lire et écrire en Python dans une certaine mesure, jetez un œil aux hubs git officiels tels que CPython et Pypa. Il y a un nombre infini de codes pour les Tsuyotsuyo, donc je pense qu'il y aura de nouvelles découvertes et des codes utiles.

Recommended Posts

Initialisation de variables globales à l'aide de décorateurs Python
Utilisation de variables globales dans les fonctions python
notes python pour l'utilisation de variables spéciales perl
# 1 [python3] Calcul simple à l'aide de variables
[Python] Variables
[Python3] Définir dynamiquement des variables globales dans une fonction
L'histoire de la manipulation des variables globales Python
Commencez à utiliser Python
À propos de Python Decorator
À propos des décorateurs Python
Scraping à l'aide de Python
Overthrow, Déclaration globale Python
Variables globales et locales 2
Manipuler Redmine à l'aide de Python Redmine
Séquence de Fibonacci utilisant Python
Nettoyage des données à l'aide de Python
Utilisation des packages Python #external
Câblage Communication Pi-SPI avec Python
Calcul de l'âge à l'aide de python
Rechercher sur Twitter avec Python
Identification de nom à l'aide de python
Notes sur l'utilisation de sous-processus Python
Essayez d'utiliser Tweepy [Python2.7]
Variables globales et locales 1
Prise en compte des décorateurs Python du type qui passe des variables
mémo python utilisant l'opérateur perl-ternaire
Aplatir à l'aide du rendement Python de
Enregistrer des images à l'aide de requêtes python3
Python: variables de classe et d'instance
[S3] CRUD avec S3 utilisant Python [Python]
[Python] Essayez d'utiliser le canevas de Tkinter
À propos des variables et des objets Python
Enregistrez une adresse IP globale avec python
Utilisation de Quaternion avec Python ~ numpy-quaternion ~
Essayez d'utiliser Kubernetes Client -Python-
[Python] Utilisation d'OpenCV avec Python (basique)
Scraping à l'aide de la syntaxe Python 3.5 Async
Surveillance des changements de site Web à l'aide de python
Gérer les variables d'environnement en Python
Publier sur Twitter en utilisant Python
Commencez à Selenium en utilisant python
Algorithme de recherche utilisant word2vec [python]
Changer la version de python à l'aide de pyenv
python: principes de base de l'utilisation de scikit-learn ①
Créer des tickets JIRA en utilisant Python
Variables de classe et d'instance Python
Contrôle d'instruments à l'aide de Python [pyvisa]
Manipulez les feuilles de calcul localement à l'aide de Python
mémo python utilisant perl --join
Web scraping avec Selenium (Python)
Guide du débutant Python (Variations / Tableaux)
[Python] Validation de JSON avec Voluptuous
Variables Python et ID d'objet
Déclaration des variables globales du langage C
Diffusion sur LINE en utilisant python
Analyse de données à l'aide de pandas python
Traduit à l'aide de googletrans en Python