Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference

Jacob Kruger jacob.kruger.work at gmail.com
Wed Mar 6 07:55:46 EST 2024


Ok, simpler version - all the code in a simpler test file, and working 
with two separate variables to explain exactly what am talking about:

# start code

from datetime import datetime, timezone, timedelta

from copy import copy


# initialise original values

dt_expiry = datetime.strptime("1970-01-01 00:00", "%Y-%m-%d 
%H:%M").replace(tzinfo=timezone.utc)

l_test = [1, 2, 3]


def do_it():
     global dt_expiry, l_test # asked python to refer to global 
variables for both

     # assign new value immediately

     dt_expiry = datetime.now()+timedelta(minutes=5)
     print(dt_expiry.strftime("%Y-%m-%d %H:%M")) # just to show new 
value has been assigned
     # grab copy of list for re-use of items
     l_temp = copy(l_test)
     # following line means l_test will later on retain value in global 
scope because it was manipulated inside function instead of just 
assigned new value
     l_test.clear()
     # replace original set of values
     for i in l_temp: l_test.append(i)
     # add new item
     l_test.append(99)
# end of do_it function

# end code


If you import the contents of that file into the python interpreter, 
dt_expiry will start off as "1970-01-01 00:00", and, if you execute 
do_it function, it will print out the new value assigned to the 
dt_expiry variable inside that function, but if you then again check the 
value of the dt_expiry variable afterwards, it's reverted to the 1970... 
value?


If I take out the line that removes values from l_test # l_test.clear() 
# before appending new value to it, then it will also not retain it's 
new/additional child items after the function exits, and will just 
revert back to [1, 2, 3] each and every time.


In other words, with some of the variable/object types, if you use a 
function that manipulates the contents of a variable, before then 
re-assigning it a new value, it seems like it might then actually 
update/manipulate the global variable, but, either just calling purely 
content retrieval functions against said objects, or assigning them new 
values from scratch seems to then ignore the global scope specified in 
the first line inside the function?


Hope this makes more sense


Jacob Kruger
+2782 413 4791
"Resistance is futile!...Acceptance is versatile..."


On 2024/03/05 20:23, dn via Python-list wrote:
> Jacob,
>
> Please reduce the problem to a small code-set which reproduces the 
> problem. If we can reproduce same, then that tells us something. At 
> the very least, we can experiment without having to expend amounts of 
> time in a (likely faulty) bid to reproduce the same environment.
>
> Also, code is the ultimate description!
>
>
> Perhaps start with a small experiment:
>
> - after l_servers is created, print its id()
> - after the global statement, print its id()
> - after the clear/reassignment, print its id()
>
> Is Python always working with the same list?
> Please advise...
>
>
> On 6/03/24 07:13, Jacob Kruger via Python-list wrote:
>> Hi there
>>
>>
>> Working with python 3.11, and, issue that confused me for a little 
>> while, trying to figure out what was occurring - unless am completely 
>> confused, or missing something - was that, for example, when having 
>> pre-defined a variable, and then included it in the global statement 
>> inside a function, that function was still referring to a completely 
>> local instance, without manipulating outside variable object at all 
>> unless I first executed a form of referral to it, before then 
>> possibly assigning a new value to it.
>>
>>
>> Now, this does not seem to occur consistently if, for example, I just 
>> run bare-bones test code inside the python interpreter, but 
>> consistently occurs inside my actual testing script.
>>
>>
>> Basically, in a file with python code in that am using for a form of
>> testing at the moment, at the top of the file, under all the import
>> statements, I initiate the existence of a list variable to make use of
>>
>> later:
>>
>>
>> # code snippet
>>
>> l_servers = []
>>
>> # end of first code snippet
>>
>>
>> Then, lower down, inside a couple of different functions, the first line
>> inside the functions includes the following:
>> # code snippet
>>      global l_servers
>> # end code snippet
>>
>> That should, in theory, mean that if I assign a value to that variable
>> inside one of the functions, it should reflect globally?
>>
>> However, it seems like that, while inside those functions, it can be
>> assigned a new list of values, but if I then return to the scope outside
>>
>> the functions, it has reverted back to being an empty list = []?
>>
>>
>> The issue seems to specifically (or not) occur when I make a call to 
>> one function, and, in the steps it's executing in one context, while 
>> it's not doing anything to the list directly, it's then making a call 
>> to the second function, which is then meant to repopulate the list 
>> with a brand new set of values.
>>
>>
>> Now, what almost seems to be occurring, is that while just 
>> manipulating the contents of a referenced variable is fine in this 
>> context, the moment I try to reassign it, that's where the issue is 
>> occurring .
>>
>>
>> Here are relevant excerpts from the file:-
>>
>>
>> # start code
>>
>> # original assignation in main part of file
>>
>> l_servers = []
>>
>>
>> # function wich is initially being executed
>>
>> def interact():
>>      global l_servers
>>      # extra code inbetween choosing what to carry out
>>
>>      # ...
>>
>>      # end of other code
>>
>>      bl_response, o_out = list_servers()
>>
>>      if bl_response: # just make sure other function call was successful
>>
>>          l_servers.clear() # first make reference to global variable
>>
>>          for srv in o_out: l_servers.append(srv) # now re-populate items
>>
>>      # end code snippet from inside interact function
>>
>> # end of interact function
>>
>> # end of code snippet
>>
>>
>> That other function being called from within, list_servers() was 
>> initially just trying to populate the values inside the global list 
>> variable itself, but was ending up in a similar fashion - reverting 
>> to initial empty value, but, the above now seems to work, as long as 
>> I first make reference to/manipulate/work with global variable 
>> instead of just trying to reassign it a brand new value/set of items?
>>
>>
>> So, am I missing something obvious, have I forgotten about something 
>> else - yes, know that if was working from within an embedded 
>> function, I might need/want to then use the nonlocal statement 
>> against that variable name, but, honestly, just not sure how this can 
>> be occurring, and, it's not just with this one list variable, etc.?
>>
>>
>> If I try simple test code from within the python interpreter, using 
>> different types of variables, this does also not seem to be the same 
>> all the time, but, don't think it can relate to an iterable like a 
>> list, or else, just in case, here is the code snippet with all the 
>> import statements from the top of that file, in case something could 
>> be overriding standard behaviour - not likely in this context, but, 
>> really not sure what's occurring:
>>
>> # import code snippet
>>
>> import requests, time
>> from requests.auth import HTTPBasicAuth
>> import psutil as psu
>> import pytz
>> import bcrypt
>> from copy import copy
>> from datetime import datetime, timedelta, timezone
>> from dateutil.parser import parse
>>
>> # end of import snippet
>>
>>
>> Thanks if you have any ideas/thoughts on the matter
>>
>>
>> Jacob Kruger
>> +2782 413 4791
>> "Resistance is futile!...Acceptance is versatile..."
>>
>>
>


More information about the Python-list mailing list