Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does global keyword required to access variable defined in outer scope?

Another question does not explain why I can't change variable time_verf without using 'global' in the example (2) but still can do it to the list in the example (4).

On the resource I found that I can not change global variable from within a function, which is clearly illustrated by these examples:

from datetime import datetime, timedelta
time_verf = datetime.now()

I think I understand why the following is working (1):

def check_global():
    global time_verf
    clean_list = time_verf + timedelta(hours=12)  # время очистки листа
    if clean_list < datetime.now():
        list_verf.clear()
        time_verf = datetime.now()
    print('ok')

>> check_global()
<< ok

Next it throws exception when I comment out line with global keyword (2):

def check_global():
    # global time_verf
    clean_list = time_verf + timedelta(hours=12)  # время очистки листа
    if clean_list < datetime.now():
        list_verf.clear()
        time_verf = datetime.now()
    print('ok')

>> check_global()
<< Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 3, in check_global
UnboundLocalError: local variable 'time_verf' referenced before assignment

And then again can be again referenced without 'global' when line with assignment commented out(3):

def check_global():
    # global time_verf
    clean_list = time_verf + timedelta(hours=12)  # время очистки листа
    if clean_list < datetime.now():
        list_verf.clear()
        # time_verf = datetime.now()
    print('ok')

>> check_global()
<< ok

But why am I allowed to update list defined in the outer scope without using global (4)?

list = []

def check_global_list():
    list.append('check')
>> check_global_list()
>> list
<< ['check']
like image 717
Vladimir Kolenov Avatar asked Nov 23 '25 02:11

Vladimir Kolenov


2 Answers

When you comment out the global time_verf statement in line 2,

1: def check_global():
2: # global time_verf
3: clean_list = time_verf + timedelta(hours=12)  # время очистки листа
4: if clean_list < datetime.now():
5:     list_verf.clear()
6:     time_verf = datetime.now()

line 6 assigns a value to a local variable time_verf. It is local because assigning it creates it as a local variable. You get an error on line 3 because it refers to the local variable that your code creates in line 6. If you did not have that assignment then time_verf would be global by default.

But whether a variable is global or not does not depend on the order of execution. You appear to expect that because line 3 on its own would make time_verf global by default, then it becomes global and remains global in line 6. But that isn't the way local variables work. The presence of line 6 changes the meaning (and correctness) of line 3. The interpreter examines the entire scope of your function and creates local variables for any names that the code assigns values to. So because of line 6, time_verf is local, even if line 3 on its own would make it global.

There are very good reasons for this behaviour. Suppose line 3 were enclosed in an if-test. Then, according to the behaviour you seem to expect, the variable would be global if the if-test were true, but local if the if-test were false.

like image 195
BoarGules Avatar answered Nov 25 '25 15:11

BoarGules


The resource you found states "If we need to assign a new value to a global variable then we can do that by declaring the variable as global.", the keyword being "assign". You can access global variables, call methods on them, mutate them without declaring them as global.

It's when you need to assign to them that you need to declare them as global.

like image 32
Roel Schroeven Avatar answered Nov 25 '25 16:11

Roel Schroeven



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!