Tout ce que vous vouliez savoir sur la portée en Python, mais avez été gêné de demander

En prévision du démarrage d'un nouveau fil de discussion sur le cours "Développeur Python" , nous avons décidé de parler de portée en Python. Qu'est-il arrivé? - Lisez le matériel ci-dessous.




Aujourd'hui, nous parlerons des fondements théoriques importants qui doivent être compris et mémorisés afin d'écrire un code compétent, lisible et beau. Nous parlerons de la portée des variables. Cet article sera utile non seulement pour les débutants, mais aussi pour les programmeurs expérimentés qui sont venus à Python à partir d'un autre langage et veulent comprendre ses mécanismes.

Les portées déterminent dans quelle partie du programme nous pouvons travailler avec une variable particulière et à partir de laquelle la variable est «masquée». Il est extrêmement important de comprendre comment utiliser uniquement les valeurs et les variables dont nous avons besoin et comment se comporte l'interpréteur de langage. Nous verrons également comment contourner les restrictions imposées par la portée aux actions avec des variables. En Python, il existe jusqu'à 3 étendues:

  • Local
  • Global
  • Non local

La dernière portée, non locale, a été ajoutée en Python 3.

Habituellement, nous parlons de portée lorsque vous êtes familier avec les fonctions. En utilisant leur exemple, nous considérerons le travail de la portée des variables.

Portée locale


Considérons une fonction qui affiche une liste some_listélément par élément:

def print_list(some_list):
    for element in some_list:
        print(element)

Ici elementet some_listsont des variables locales qui ne sont visibles qu'à l'intérieur de la fonction, et qui ne peuvent pas être utilisées à l'extérieur avec les valeurs qui leur ont été affectées à l'intérieur de la fonction pendant son fonctionnement. Autrement dit, si nous appelons dans le corps principal du programme print(element), nous obtenons une erreur:

NameError: name 'element' is not defined


Maintenant, nous allons faire ce qui suit:

def print_list(some_list):
    for element in some_list:
        print(element) 

element = 'q'
print_list([1, 2, 3])
print(element) 


Et nous obtenons:

1
2
3
q

Ici la variable elementà l'intérieur de la fonction et la variable du même nom à l'extérieur sont deux variables différentes, leurs valeurs ne se croisent pas et ne s'échangent pas. Ils sont appelés les mêmes, mais font référence à différents objets en mémoire. De plus, un élément nommé variable à l'intérieur de la fonction vit aussi longtemps que la fonction est exécutée et pas plus. Mais soyez prudent afin de donner le même nom aux variables locales et globales, maintenant je vais vous montrer pourquoi:

def print_list(some_list):
    for element in sudden_list:
        print(element) 

sudden_list = [0, 0, 0]
print_list([1, 2, 3])

Résultat:

0
0
0

Veuillez noter que l'interprète ne nous a pas signalé d'erreurs. Et tout cela parce qu'il sudden_listest dans la portée globale, c'est-à-dire de l'intérieur de la fonction, print_listnous pouvons y accéder, car de l'intérieur, vous pouvez voir ce qui se passe à l'extérieur. Pour cette raison, essayez de nommer les variables locales à l'intérieur de la fonction différemment de ce que vous appelez des variables dans la portée globale.

Il est important de parler des constantes ici. Il n'y a aucune différence pour l'interpréteur Python ce que vous appelez une variable, donc le code ci-dessus serait mieux réécrit comme suit:

SUDDEN_LIST = [0, 0, 0]

def print_list(some_list):
    for element in SUDDEN_LIST:
        print(element) 

print_list([1, 2, 3]) 

Maintenant, tout est en place. Le fait est qu'en Python, vous ne pouvez pas en quelque sorte définir strictement une constante comme un objet qui ne devrait pas être modifié. Ainsi, la façon dont vous utilisez la valeur d'une variable dont le nom est écrit en majuscules ne reste que dans votre conscience. Une autre question est que de cette manière la variable enregistrée indiquera clairement à celui qui lit votre code que la variable ne changera nulle part. Ou du moins, ça ne devrait pas.

Portée mondiale


Python possède un mot global- clé qui vous permet de modifier la valeur d'une variable globale à partir d'une fonction. Il est écrit avant le nom de la variable, qui sera considéré comme global dans la fonction. Comme vous pouvez le voir dans l'exemple, maintenant la valeur de la variable candyaugmente, et notez que nous ne la transmettons pas comme argument à la fonction get_candy().

candy = 5

def get_candy():
    global candy 
    candy += 1
    print('  {} .'.format(candy))
    
get_candy()
get_candy()
print(candy)


En conséquence, nous obtenons:


	  6 .
  7 .
7


Cependant, la modification de la valeur d'une variable globale à partir de la fonction n'est pas la meilleure pratique, et il vaut mieux ne pas le faire, car cela ne contribue pas à la lisibilité du code. Le plus petit ce qui se passe à l'intérieur de la fonction dépendra de la portée globale, mieux ce sera.

Life hack : Afin de ne pas souffrir du nommage des variables, vous pouvez mettre le code principal du programme dans une fonction main(), puis toutes les variables qui seront déclarées à l'intérieur de cette fonction resteront locales et ne gâcheront pas la portée globale, augmentant la probabilité d'une erreur.

Portée non locale


Ce concept est apparu dans Python 3 avec le mot-clé nonlocal. La logique de son écriture est à peu près la même que celle de global. Cependant, nonlocalil existe une fonctionnalité. NonlocalIl est le plus souvent utilisé dans les fonctions imbriquées lorsque nous voulons faire comprendre à l'interpréteur que pour une fonction imbriquée une certaine variable n'est pas locale, mais elle n'est pas globale au sens général.

def get_candy():
    candy = 5
    def increment_candy(): 
        nonlocal candy
        candy += 1
        return candy
    return increment_candy
    
result = get_candy()()
print(' {} .'.format(result))

Résultat:

 6 .

À quel point il est utile pour vous de décider par vous-même. Vous pouvez trouver plus d'exemples ici .

En conclusion, plusieurs règles peuvent être formulées:

  1. De l'intérieur de la fonction se trouvent des variables visibles qui ont été définies à l'intérieur et à l'extérieur de celle-ci. Les variables définies en interne sont locales et globalement externes.
  2. En dehors des fonctions, aucune variable définie à l'intérieur n'est visible.
  3. , global.
  4. nonlocal , , .

C'est tout, j'espère que ce matériel vous a été utile et qu'il a au moins apporté un peu de lumière sur le fonctionnement de l'oscilloscope en Python. Après avoir traité des étendues, vous en ferez une autre sur le chemin de la création d'un code beau et lisible.

Je veux également inviter tout le monde à un webinaire gratuit d'OTUS, où nous étudierons un outil tel que l'annotation de type en Python: discutez des raisons pour lesquelles beaucoup de gens le sous-estiment, considérez un certain nombre d'exemples de la pratique militaire lorsque l'annotation de type pourrait sauver ou sauver la situation. Voyons comment et quand implémenter la vérification de type sur vos projets .

All Articles