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