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 11:40:40 EST 2024


Matt, other mail is more relevant - seems to maybe have more to do with 
different behavour if import code, or not - no, does not make sense to 
me - but, here's the command line contents including printing out id() 
results, but, only working via importing code:

#---start session---

C:\temp\py_try>type scoping2.py
from datetime import datetime, timezone, timedelta

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

def do_it():
     global dt_expiry
     dt_expiry = datetime.now()+timedelta(minutes=5)
     print("date value", dt_expiry.strftime("%Y-%m-%d %H:%M"))
     print("ID", id(dt_expiry))
# end of do_it function


C:\temp\py_try>python
Python 3.11.7 (tags/v3.11.7:fa7a6f2, Dec  4 2023, 19:24:49) [MSC v.1937 
64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
 >>> from scoping2 import *
 >>> print(dt_expiry)
1970-01-01 00:00:00+00:00
 >>> print(id(dt_expiry))
1808577867152
 >>> do_it()
date value 2024-03-06 18:39
ID 1808572660736
 >>> print(dt_expiry)
1970-01-01 00:00:00+00:00
 >>> print(id(dt_expiry))
1808577867152
 >>>
---end session---

As in, the two different ID values are being returned outside and inside 
the function, whereas, if I included that bit inside the interpreter 
while typing code manually, chances are the same ID would be retained 
both inside and outside function.

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


On 2024/03/06 15:57, Mats Wichmann via Python-list wrote:
> On 3/6/24 05:55, Jacob Kruger via Python-list wrote:
>> Ok, simpler version - all the code in a simpler test file, and 
>> working with two separate variables to explain exactly what am 
>> talking about:
>
>> 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
>
> No, it doesn't. Your code is working as one would expect. For example, 
> adding prints for the l_test variable, and removing the .clear() which 
> you claim makes it not work, shows me:
>
> before: l_test=[1, 2, 3], id(l_test)=140153285385856
> leaving do_it: l_test=[1, 2, 3, 1, 2, 3, 99], id(l_test)=140153285385856
> after: l_test=[1, 2, 3, 1, 2, 3, 99], id(l_test)=140153285385856
>
> It's the same list object, as you can see by the id values. And the 
> list is updating as expected.
>
> And... you don't need the global statement for l_test. As it's 
> mutable, you can mutate it in the function; the global only acts on 
> assignment. Using "global" for that may make your intent more clear to 
> readers though, although static checkers will grumble at you.
>
> You must be doing something additional that you're not telling us about.
>
>


More information about the Python-list mailing list