In anticipation of the start of a new thread on the course "Python Developer" , we decided to talk about scope in Python. What came of this? - Read the material below.
Today we will talk about important theoretical foundations that must be understood and remembered in order to write competent, readable and beautiful code. We will talk about the scope of variables. This article will be useful not only for beginners, but also for experienced programmers who came to Python from another language and want to understand its mechanics.Scopes determine in which part of the program we can work with a particular variable, and from which the variable is “hidden”. It is extremely important to understand how to use only those values and variables that we need, and how the language interpreter behaves. We’ll also see how to circumvent the restrictions imposed by scope on actions with variables. In Python, there are as many as 3 scopes:The last, nonlocal scope, was added in Python 3.Usually, we are talking about scope when familiar with functions. Using their example, we will consider the work of the scope of variables.Local scope
Consider a function that displays a list some_list
element by element:def print_list(some_list):
for element in some_list:
print(element)
Here element
and some_list
are local variables that are visible only inside the function, and which cannot be used outside it with the values that were assigned to them inside the function during its operation. That is, if we call in the main body of the program print(element)
, we get an error:NameError: name 'element' is not defined
Now we will do the following:def print_list(some_list):
for element in some_list:
print(element)
element = 'q'
print_list([1, 2, 3])
print(element)
And we get:1
2
3
q
Here the variable element
inside the function and the variable with the same name outside it are two different variables, their values do not cross and do not interchange. They are called the same, but refer to different objects in memory. Moreover, a variable named element inside the function lives as long as the function is executed and no more. But be careful in order to give local and global variables the same name, now I will show why:def print_list(some_list):
for element in sudden_list:
print(element)
sudden_list = [0, 0, 0]
print_list([1, 2, 3])
Result:0
0
0
Please note that the interpreter did not indicate errors to us. And all because it sudden_list
is in the global scope, that is, from the inside of the function print_list
we can access it, because from the inside you can see what is happening outside. For the reason of such mechanics of work, try to name local variables inside the function differently from what you call variables in the global scope.It is important to talk about constants here. There is no difference to the Python interpreter what you call a variable, so the code above would be better rewritten as follows:SUDDEN_LIST = [0, 0, 0]
def print_list(some_list):
for element in SUDDEN_LIST:
print(element)
print_list([1, 2, 3])
Now everything is in place. The thing is, in Python you cannot somehow strictly define a constant as an object that should not be modified. So the way you use the value of a variable whose name is written in capital letters remains only on your conscience. Another question is that in this way the recorded variable will make it clear to whoever reads your code that the variable will not change anywhere. Or at least it shouldn't.Global scope
Python has a keyword global
that allows you to change the value of a global variable from within a function. It is written before the variable name, which will be considered global inside the function. As you can see from the example, now the value of the variable is candy
increasing, and note that we do not pass it as an argument to the function get_candy()
.candy = 5
def get_candy():
global candy
candy += 1
print(' {} .'.format(candy))
get_candy()
get_candy()
print(candy)
As a result, we get:
6 .
7 .
7
However, changing the value of a global variable from within the function is not the best practice, and it is better not to do so, because it does not contribute to code readability. The smaller what happens inside the function will depend on the global scope, the better.Life hack : In order not to suffer from the naming of variables, you can put the main program code into a function main()
, then all the variables that will be declared inside this function will remain local and will not spoil the global scope, increasing the likelihood of an error.Nonlocal scope
This concept appeared in Python 3 along with the keyword nonlocal
. The logic of his writing is about the same as that of global
. However, nonlocal
there is a feature. Nonlocal
It is most often used in nested functions when we want to make the interpreter understand that for a nested function a certain variable is not local, but it is not global in the general sense.def get_candy():
candy = 5
def increment_candy():
nonlocal candy
candy += 1
return candy
return increment_candy
result = get_candy()()
print(' {} .'.format(result))
Result: 6 .
How useful it is for you to decide for yourself. You can find more examples here .As a conclusion, several rules can be formulated:- From within the function are visible variables that have been defined both inside and outside it. Variables defined internally are local and externally global.
- Outside of functions, no variables defined inside them are visible.
- ,
global
. - nonlocal , , .
That's all, I hope this material was useful to you, and it shed at least a little light on how the scope works in Python. Having dealt with scopes, you will make another ours on the way to creating beautiful and readable code.I also want to invite everyone to a free webinar from OTUS, where we will study a tool such as type annotation in Python: discuss the reasons why many people underestimate it, consider a number of examples from military practice when type annotation could save or save the situation. Let's talk about how and when to implement type checking on your projects .