Variables visibility and scope
Reading time10 minEn bref
Résumé de l’article
Dans cet article, nous discutons de la visibilité des variables.
Cela désigne la portée dans laquelle les variables existent et peuvent être utilisées.
En particulier, nous discutons de la différence entre les variables locales et globales.
Points clés
-
Les variables locales ne sont visibles que dans la portée de la fonction qui les utilise.
-
Les variables globales sont accessibles partout dans le programme.
-
Les variables globales doivent être évitées au profit des variables locales.
Contenu de l’article
Comme vu dans la session 1, une variable associe explicitement un nom à une valeur et occupe implicitement un espace en mémoire principale, dont la taille dépend du type de variable.
La valeur actuellement associée à la variable peut être accédée via le nom de la variable.
En raison des limitations de mémoire, toutes les variables n’existent pas tout au long de la vie d’un programme.
Un composant de l’interpréteur Python, appelé “ramasse-miettes” (garbage collector), supprime les variables qui ne peuvent plus être utilisées, libérant ainsi la mémoire qu’elles occupaient.
La visibilité d’une variable détermine sa durée de vie, et deux types de visibilité sont considérés en Python, à savoir les variables locales
et globales
.
1 — Variables locales vs globales
Les variables locales sont définies à l’intérieur d’une fonction et ne sont pas accessibles en dehors.
Dans cet exemple, nous définissons deux variables a
et b
qui sont locales à la fonction example
.
Elles n’existent que dans example
et cessent d’exister une fois que la fonction/procédure a retourné/terminé.
# Define a function
def example (a):
"""
This is an example function with two local variables.
In:
* a: An argument of the function.
Out:
* None.
"""
# Define a local variable
b = 2
# Print variables
print(a, b)
# Call it and try to access variables
example(1)
print(a, b)
/**
* To run this code, you need to have Java installed on your computer, then:
* - Create a file named `Main.java` in a directory of your choice.
* - Copy this code in the file.
* - Open a terminal in the directory where the file is located.
* - Run the command `javac Main.java` to compile the code.
* - Run the command `java -ea Main` to execute the compiled code.
* Note: '-ea' is an option to enable assertions in Java.
*/
public class Main {
/**
* This is an example function with two local variables
*
* @param a An argument of the function.
*/
public static void example(int a) {
// Define a local variable
int b = 2;
// Print variables
System.out.println(a + " " + b);
}
/**
* This is the entry point of your program.
* It contains the first codes that are going to be executed.
*
* @param args Command line arguments received.
*/
public static void main(String[] args) {
// Call it and try to access variables
example(1);
System.out.println(a + " " + b);
}
}
Voici la sortie obtenue :
1 2
Traceback (most recent call last):
File "exaple.py", line 22, in <module>
print(a, b)
NameError: name 'a' is not defined
Main.java:33: error: cannot find symbol
System.out.println(a + " " + b);
^
symbol: variable a
location: class Main
Main.java:33: error: cannot find symbol
System.out.println(a + " " + b);
^
symbol: variable b
location: class Main
2 errors
Les variables globales sont définies en dehors de toutes les fonctions et accessibles partout dans le code.
Déclarons une variable globale a
, mais aussi une variable locale appelée a
, et affichons-les :
# Define a global variable
a = 1
# Define a function
def example ():
"""
Example function with a local variable, also named "a".
In:
* None.
Out:
* None.
"""
# Define a local variable
a = 2
# Print a to see which one we use
print(a)
# See what we got
print(a)
example()
print(a)
/**
* To run this code, you need to have Java installed on your computer, then:
* - Create a file named `Main.java` in a directory of your choice.
* - Copy this code in the file.
* - Open a terminal in the directory where the file is located.
* - Run the command `javac Main.java` to compile the code.
* - Run the command `java -ea Main` to execute the compiled code.
* Note: '-ea' is an option to enable assertions in Java.
*/
public class Main {
/**
* Define a global variable (in Java, we use a class-level variable).
*/
static int a = 1;
/**
* Example function with a local variable, also named "a".
*/
public static void example() {
// Define a local variable
int a = 2;
// Print a to see which one we use
System.out.println(a);
}
/**
* This is the entry point of your program.
* It contains the first codes that are going to be executed.
*
* @param args Command line arguments received.
*/
public static void main(String[] args) {
// See what we got
System.out.println(a);
example();
System.out.println(a);
}
}
Voici la sortie obtenue :
1
2
1
1
2
1
Notez que les variables locales “cachent” les variables globales portant le même nom.
2 — Les mots-clés global et nonlocal
Python offre deux mots-clés pour jouer avec la visibilité des variables.
Le mot-clé global
est utilisé pour modifier une variable globale à l’intérieur d’une fonction.
Adaptation du code ci-dessus, pour indiquer dans example
que a
est global.
Ici, le mot-clé global
indique de ne pas redéfinir une nouvelle variable, mais de trouver une variable existante en mémoire globale.
# Define a global variable
a = 1
# Define a function
def example ():
"""
Example function with access to global variable "a".
In:
* None.
Out:
* None.
"""
# Indicate that a exists in the global scope
global a
# Update global variable
a = 2
# Print global variable
print(a)
# See what we got
print(a)
example()
print(a)
/**
* To run this code, you need to have Java installed on your computer, then:
* - Create a file named `Main.java` in a directory of your choice.
* - Copy this code in the file.
* - Open a terminal in the directory where the file is located.
* - Run the command `javac Main.java` to compile the code.
* - Run the command `java -ea Main` to execute the compiled code.
* Note: '-ea' is an option to enable assertions in Java.
*/
public class Main {
/**
* Define a global variable (in Java, we use a class-level variable).
*/
static int a = 1;
/**
* Example function with access to global variable "a".
*/
public static void example() {
// Update global variable
a = 2;
// Print global variable
System.out.println(a);
}
/**
* This is the entry point of your program.
* It contains the first codes that are going to be executed.
*
* @param args Command line arguments received.
*/
public static void main(String[] args) {
// See what we got
System.out.println(a);
example();
System.out.println(a);
}
}
Voici la sortie obtenue :
1
2
2
1
2
2
Le mot-clé nonlocal
est utilisé dans les fonctions imbriquées pour modifier une variable dans la portée englobante.
C’est une situation assez particulière, mais cela peut être utile lorsqu’on travaille avec des fonctions imbriquées.
Adaptation du code ci-dessus avec une fonction imbriquée.
Notez que Java gère les portées différemment, il n’y a donc pas d’équivalent.
# Define a global variable
a = 1
# Define a function
def example ():
"""
Example function with a nested function.
Note that "inner" cannot be called from outside the body of function "example".
In:
* None.
Out:
* None.
"""
# Local variable
a = 2
# Inner function
def inner ():
nonlocal a
a = 3
# Call inner function
print(a)
inner()
print(a)
# See what we got
print(a)
example()
print(a)
Voici la sortie obtenue :
1
2
3
1
1
2
3
1
Les variables locales et globales visibles sont stockées dans deux structures de données séparées (i.e., dictionnaires) qui peuvent être affichées en appelant respectivement les fonctions locals()
et globals()
.
En général, il est préférable d’éviter d’utiliser des variables globales, car elles peuvent être une source d’erreurs.
Par exemple, considérez la fonction suivante :
# Define a global variable
a = 1
# Define a function
def example (b):
"""
Example function.
In:
* b: An argument of the function.
Out:
* The product of a and b.
"""
# Indicate that a exists in the global scope
global a
# Update a
a += 1
# Return a computation that depends on a and b
return a * b
# See what we got
res = example(2)
print(res)
res = example(2)
print(res)
/**
* To run this code, you need to have Java installed on your computer, then:
* - Create a file named `Main.java` in a directory of your choice.
* - Copy this code in the file.
* - Open a terminal in the directory where the file is located.
* - Run the command `javac Main.java` to compile the code.
* - Run the command `java -ea Main` to execute the compiled code.
* Note: '-ea' is an option to enable assertions in Java.
*/
public class Main {
/**
* Define a global variable (in Java, we use a class-level variable).
*/
static int a = 1;
/**
* Example function.
*
* @param b An argument of the function.
*/
public static int example(int b) {
// Update a
a += 1;
// Return a computation that depends on a and b
return a * b;
}
/**
* This is the entry point of your program.
* It contains the first codes that are going to be executed.
*
* @param args Command line arguments received.
*/
public static void main(String[] args) {
// See what we got
int res = example(2);
System.out.println(res);
res = example(2);
System.out.println(res);
}
}
L’appeler deux fois conduira à deux résultats différents (4
, puis 6
), ce qui n’est pas un comportement standard.
Pour aller plus loin
On dirait que cette section est vide !
Y a-t-il quelque chose que vous auriez aimé voir ici ?
Faites-le nous savoir sur le serveur Discord !
Peut-être pouvons-nous l’ajouter rapidement.
Sinon, cela nous aidera à améliorer le cours pour l’année prochaine !
Pour aller au-delà
- Java Modifiers
Certains langages, comme Java, fournissent des stratégies supplémentaires pour déterminer les niveaux d’accès aux variables et autres composants.