Mailing List Archive

Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference
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..."


--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
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..."
>
>

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
On 05Mar2024 20:13, Jacob Kruger <jacob.kruger.work@gmail.com> wrote:
>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 .

Because there are no variable definitions in Python, when you write a
function Python does a static analysis of it to decide which variables
are local and which are not. If there's an assignment to a variable, it
is a local variable. _Regardless_ of whether that assignment has been
executed, or gets executed at all (eg in an if-statement branch which
doesn't fire).

You can use `global` or `nonlocal` to change where Python looks for a
particular name.

In the code below, `f1` has no local variables and `f2` has an `x` and
`l1` local variable.

x = 1
l1 = [1, 2, 3]

def f1():
print("f1 ...")
l1[1] = 5 # _not_ an assignment to "l1"
print("in f1, x =", x, "l1 =", l1)

def f2():
print("f2 ...")
x = 3
l1 = [6, 7, 9] # assignment to "l1"
print("in f2, x =", x, "l1 =", l1)

print("outside, x =", x, "l1 =", l1)
f1()
print("outside after f1, x =", x, "l1 =", l1)
f2()
print("outside after f2, x =", x, "l1 =", l1)

Cheers,
Cameron Simpson <cs@cskk.id.au>
--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
On 2024-03-05, Cameron Simpson via Python-list <python-list@python.org> wrote:

> Because there are no variable definitions in Python, when you write
> a function Python does a static analysis of it to decide which
> variables are local and which are not. If there's an assignment to a
> variable, it is a local variable. _Regardless_ of whether that
> assignment has been executed, or gets executed at all (eg in an
> if-statement branch which doesn't fire).

Unfortunately, crap "information" sites like geeksforgeeks often
describe this either incorrectly or so vaguely as to be worthless.
From the page https://www.geeksforgeeks.org/global-local-variables-python/

Python Global variables are those which are not defined inside
any function and have a global scope whereas Python local
variables are those which are defined inside a function and their
scope is limited to that function only.

Since "define" (in this context) isn't a term of art in Python, and
it's never defined on the page in question, the quoted paragraph is
not meaningful: it simply says that "global variables are global and
local variables are local".

That page goes on to say:

In other words, we can say that local variables are accessible
only inside the function in which it was initialized

This is equally crap. It doesn't matter whether the variable is
initialized or not. As Cameron correctly stated, if a function
contains an assignment to a variable, and that variable is not
declared global, then that variable is local. For example:

def foo():
print(s)
if 0:
s = "there"
print(s)

In the function above s _is_not_ initialized in the function foo().
However, foo() does contain an assignment to s, therefore s is local
unless declared global/nonlocal. [.And the first print() will throw an
exception even if there is a value bound to the global name 's'.]

Unfortunately (presumably thanks to SEO) the enshittification of
Google has reached the point where searching for info on things like
Python name scope, the first page of links are to worthless sites like
geeksforgeeks.

--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
On 05/03/2024 22:46, Grant Edwards via Python-list wrote:
> Unfortunately (presumably thanks to SEO) the enshittification of
> Google has reached the point where searching for info on things like
> Python name scope, the first page of links are to worthless sites like
> geeksforgeeks.
And not just Google, I just tried bing, yahoo and duckduckgo
and they are all the same. Not a one listed anything from
python.org on the first page... In fact it didn't even appear
in the first 100 listings, although wikipedia did manage an
entry, eventually.

--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
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..."
>>
>>
>
--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
So, this does not make sense to me in terms of the following snippet
from the official python docs page:

https://docs.python.org/3/faq/programming.html


"In Python, variables that are only referenced inside a function are
implicitly global. If a variable is assigned a value anywhere within the
function’s body, it’s assumed to be a local unless explicitly declared
as global."


So, I would then assume that if I explicitly include a variable name
inside the global statement, then even just assigning it a new value
should update the variable in the global context, outside the function?


Unless this is something that changed from 3.11 to 3.12 - since that
snippet is more or less referring to 3.12, but, don't think it was
changed in any way?


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


On 2024/03/06 14:55, Jacob Kruger 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:
>
> # 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..."
>>>
>>>
>>
--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
On 3/6/2024 5:59 AM, Alan Gauld via Python-list wrote:
> On 05/03/2024 22:46, Grant Edwards via Python-list wrote:
>> Unfortunately (presumably thanks to SEO) the enshittification of
>> Google has reached the point where searching for info on things like
>> Python name scope, the first page of links are to worthless sites like
>> geeksforgeeks.
> And not just Google, I just tried bing, yahoo and duckduckgo
> and they are all the same. Not a one listed anything from
> python.org on the first page... In fact it didn't even appear
> in the first 100 listings, although wikipedia did manage an
> entry, eventually.

I don't know ... I just searched for "python local vs global variables"
and a python.org page on it was the second hit. I usually use StartPage
- who knows where they aggregate from - but the same search on Google
and Bing also popped up the python.org link as the second hit. As usual
Bing was a nasty experience, though.

Still, if your search phrase isn't as well focused as that or you are
less lucky, for sure you'll get all sorts of junk.

--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
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.


--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
On 3/6/2024 7:55 AM, 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:
>
> # 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?

Not when I run your code. With a little annotation added to the print
statements I get (I added the import statements to make it run, and I
used the same date-time formatting for all three print statements):

List before: [1, 2, 3]
start: 1970-01-01 00:00
inside after reassignment: 2024-03-06 08:57
outside after: 2024-03-06 08:57
List after: [1, 2, 3, 99]

As an aside, you have gone to some trouble to copy, clear, and
reconstruct l_test. It would be simpler like this (and you wouldn't
have to import the "copy" library):

l_temp = l_test[:]
l_test = []

Instead of those lines and then this:

for i in l_temp: l_test.append(i)

you could achieve the same thing with this single statement:

l_test = l_test[:]
>
> 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..."
>>>
>>>
>>

--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
Op 6/03/2024 om 13:55 schreef Jacob Kruger via Python-list:
> If you import the contents of that file into the python interpreter, [...]

What exactly to you mean by "import the contents of that file into the
python interpreter"? Other people have put your code in a script,
executed it, and saw it working as expected. I pasted in IPython, and
likewise saw it working as expected, and the same with IDLE. It seems to
me you must be doing something different from us; maybe the way you
execute that code might be the key to this whole confusion.

--
"Il semble que la perfection soit atteinte non quand il n'y a plus rien à
ajouter, mais quand il n'y a plus rien à retrancher."
"Perfectie is niet bereikt als er niets meer toe te voegen is, maar als er
niets meer weg te nemen is."
-- Antoine de Saint-Exupéry

--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
Op 6/03/2024 om 16:39 schreef Roel Schroeven via Python-list:
> Op 6/03/2024 om 13:55 schreef Jacob Kruger via Python-list:
>> If you import the contents of that file into the python interpreter,
>> [...]
>
> What exactly to you mean by "import the contents of that file into the
> python interpreter"? Other people have put your code in a script,
> executed it, and saw it working as expected. I pasted in IPython, and
> likewise saw it working as expected, and the same with IDLE. It seems
> to me you must be doing something different from us; maybe the way you
> execute that code might be the key to this whole confusion.
(As an aside, I made a type; "What exactly _do_ you mean" is what I
meant to type)

If you want, you can play with the code online here:
https://tio.run/##pVPbitswEH3XVwwJITaNQ9KllATy0EKhL/2AUsqiWKNkWlkykrzZ7NJvT0e@JWT7VmPsEZozc87RqD7Ho7MPl8sUQpQ@QukUCqG9q0DJiJEqBKpqx1vDegHp@@JsHyk0UfaY0tXnIT/FQogpkKVI0lBAcJ4OZKWBJ2kaDEKo@IjPNfkz7MYGyxB9nYJsst58XBWrNb@wWm1Xq8kCJrPvxawqZgpmX7ezb5N86bE2ssQsvpDVbjewWzaxzIUwjxFD5PI/1gt4v4CHn0xKoQblHilm@VYAPwfj9kxrpLOAHjcFGX6jgrp1CqIDjxp9CnrMk/Qk9wYDaOdh7@JRtCUTMtDBgsVTp5edYbuIZZpzl/NP@dadsvzdaG1WkW2Yy@5D3mJqTzZmIzK5pTu37p3JmcOvhkUw2XB0pxsmRxlgj2h7jqh6ygcv990pOg18ZLEV5bFo0ulpoIhVaHOTP1XNvFN21rmV91W0M8adyB64hEWoUNowGHoiY8CwVg/sp8coyQ722MHTwEWRCZYy9SVGMd9KWqqbBFWcGkgh6MaWkbgOryNKlSi2igdZV8kj6RCXpUHps4FtPz/X4QwYU6F@RlNSMoESv071digk6xqtymgoJVXXMdl027DP22xyvg8cpfLt/I0KRL@RLiDwhHanPP@M3Brn@bAu2mdc6/k4B7vXMfxzs98R2L12/@tOPrb48owlz1fH575TMTbsr8sb@CfNR3kH@x9@l8tf

(sorry for the long URL; that's where tio.run puts the code)

Again it works as expected, but with or without the l_test.clear() line.

--
"Il semble que la perfection soit atteinte non quand il n'y a plus rien à
ajouter, mais quand il n'y a plus rien à retrancher."
"Perfectie is niet bereikt als er niets meer toe te voegen is, maar als er
niets meer weg te nemen is."
-- Antoine de Saint-Exupéry

--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
Thanks for all your input people, and, yes, I know that besides the
scope oddities the rest of the code is not my normal style either - was
partly due to forms of experimentation to try figure out what could be
causing issues. For example, instead of [:] syntax, was specifically
using copy() to make sure was not interacting with original variable
values, etc.


This will be a bit longer - copying-pasting command line output here to
show you what I truly mean - first session, where I am importing code
into interpreter and second session where I retype exact same code
behave differently:

#---first 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(dt_expiry.strftime("%Y-%m-%d %H:%M"))
# 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
>>> do_it()
2024-03-06 18:12
>>> print(dt_expiry)
1970-01-01 00:00:00+00:00
>>>

#---end first session---


And, if I now retype the contents of the file into the python
interpreter instead:

#---start second session---

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 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(dt_expiry.strftime("%Y-%m-%d %H:%M"))
...
>>> print(dt_expiry)
1970-01-01 00:00:00+00:00
>>> do_it()
2024-03-06 18:20
>>> print(dt_expiry)
2024-03-06 18:20:03.909825
>>>

#---end second session---


So, in the second session, where retyped everything, it behaves as I
would expect it to, but, during first session, the variable is being
treated as a local variable inside the function - no code differences
since literally copied-pasted each and every line into console, but, a
different behaviour nonetheless?


So, yes, know this comes across like some form of a scam/joke, or
list-garbage, since it doesn't make any sense to me at all, but still
just wondering if missing something, or should I shift over to 3.12 to
see if if works differently, or just try reinstalling 3.11 from scratch,
or should I retry the above in something like the VS code console, or a
different python console, etc.?


Sorry


Jacob Kruger

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


On 2024/03/06 16:01, Thomas Passin via Python-list wrote:
> On 3/6/2024 7:55 AM, 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:
>>
>> # 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?
>
> Not when I run your code. With a little annotation added to the print
> statements I get (I added the import statements to make it run, and I
> used the same date-time formatting for all three print statements):
>
> List before: [1, 2, 3]
> start: 1970-01-01 00:00
> inside after reassignment: 2024-03-06 08:57
> outside after: 2024-03-06 08:57
> List after: [1, 2, 3, 99]
>
> As an aside, you have gone to some trouble to copy, clear, and
> reconstruct l_test.  It would be simpler like this (and you wouldn't
> have to import the "copy" library):
>
>     l_temp = l_test[:]
>     l_test = []
>
> Instead of those lines and then this:
>
>     for i in l_temp: l_test.append(i)
>
> you could achieve the same thing with this single statement:
>
>     l_test = l_test[:]
>>
>> 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..."
>>>>
>>>>
>>>
>
--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
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.
>
>
--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
You'll see more details in other mail, but, here I am firing up standard
python interpreter from within windows terminal, and then executing
following line:

from scoping2 import *


And, this is under windows 11 windows terminal, which is where I
generally interact with my python code, via command line - generally
working with flask, and/or other forms of command line interaction, most
of the time.


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


On 2024/03/06 17:39, Roel Schroeven via Python-list wrote:
> Op 6/03/2024 om 13:55 schreef Jacob Kruger via Python-list:
>> If you import the contents of that file into the python interpreter,
>> [...]
>
> What exactly to you mean by "import the contents of that file into the
> python interpreter"? Other people have put your code in a script,
> executed it, and saw it working as expected. I pasted in IPython, and
> likewise saw it working as expected, and the same with IDLE. It seems
> to me you must be doing something different from us; maybe the way you
> execute that code might be the key to this whole confusion.
>
--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
On 3/6/24 08:28, Jacob Kruger via Python-list wrote:

> 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 *

And it becomes clear: only do `from ... import *` when the module has been specifically designed to support that.

If you were to also do `import scoping2` and, after calling `do_it()`, `print(scoping2.dt_expiry)`, you would see that
it had changed.

I know there are good explanations for how variables and names work in Python, but I couldn't find any at the moment.
Sorry.

--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
Ok, Ethan, that makes sense - I generally work with modules in folders,
etc., but, this was just test code, but, 'see' if I instead import
scoping2 as sc2, and then refer to sc2.dt_expiry and sc2.do_it, then it
does operate as it should - thanks, again.


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


On 2024/03/06 18:57, Ethan Furman via Python-list wrote:
> On 3/6/24 08:28, Jacob Kruger via Python-list wrote:
>
> > 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 *
>
> And it becomes clear:  only do `from ... import *` when the module has
> been specifically designed to support that.
>
> If you were to also do `import scoping2` and, after calling `do_it()`,
> `print(scoping2.dt_expiry)`, you would see that it had changed.
>
> I know there are good explanations for how variables and names work in
> Python, but I couldn't find any at the moment. Sorry.
>
> --
> ~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
Op 6/03/2024 om 17:40 schreef Jacob Kruger via Python-list:
> >>> from scoping2 import *
Ah yes, that explains what's happening. After that statement, the name
dt_expiry in the current namespace is bound to the same object that the
name dt_expiry in the namespace of module scoping2 is bound to. Function
do_it re-binds that last one to a new one, with the new value; name
dt_expiry in the current namespace is still bound to the old object. (If
all of that sounds like gibberish, have a look at "Facts and myths about
Python names and values" (text:
https://nedbatchelder.com/text/names.html; slides and video:
https://nedbatchelder.com/text/names1.html)

I would advice not to use 'import *', if at all possible, for multiple
reasons, one of which is to prevent problems like this.

I would also advice not to use global variables from other modules
directly, and in fact would advice to minimize the use of globals in
general as much as possible. If you need to keep state between methods,
it might be better to use a class.

--
"There is a theory which states that if ever anyone discovers exactly what the
Universe is for and why it is here, it will instantly disappear and be
replaced by something even more bizarre and inexplicable.
There is another theory which states that this has already happened."
-- Douglas Adams, The Restaurant at the End of the Universe

--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
On 2024-03-06, Roel Schroeven via Python-list <python-list@python.org> wrote:
> Op 6/03/2024 om 17:40 schreef Jacob Kruger via Python-list:
>> >>> from scoping2 import *
>
> [...]
>
> I would advice not to use 'import *', if at all possible, for multiple
> reasons, one of which is to prevent problems like this.

Unfortunately, many (most?) tutorials for particular modules (and even
example code in the Python documentation itself) are all written
assuming that you do "from <module> import *". It saves the tutorial
write a few keystrokes, but causes untold trouble for people who learn
incorrectly that "from <module> import *" is the proper way to do
things.

> I would also advice not to use global variables from other modules
> directly, and in fact would advice to minimize the use of globals in
> general as much as possible. If you need to keep state between
> methods, it might be better to use a class.


--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
Grant Edwards via Python-list schreef op 6/03/2024 om 18:59:
> On 2024-03-06, Roel Schroeven via Python-list <python-list@python.org>
> wrote:
> > Op 6/03/2024 om 17:40 schreef Jacob Kruger via Python-list:
> >> >>> from scoping2 import *
> >
> > [...]
> >
> > I would advice not to use 'import *', if at all possible, for
> multiple > reasons, one of which is to prevent problems like this.
>
> Unfortunately, many (most?) tutorials for particular modules (and even
> example code in the Python documentation itself) are all written
> assuming that you do "from <module> import *". It saves the tutorial
> write a few keystrokes, but causes untold trouble for people who learn
> incorrectly that "from <module> import *" is the proper way to do
> things.

I know ... it's really irritating.

--
"There is a theory which states that if ever anyone discovers exactly what the
Universe is for and why it is here, it will instantly disappear and be
replaced by something even more bizarre and inexplicable.
There is another theory which states that this has already happened."
-- Douglas Adams, The Restaurant at the End of the Universe

--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
On 7/03/24 05:28, Jacob Kruger via Python-list wrote:
...
> So, yes, know this comes across like some form of a scam/joke, or
> list-garbage, since it doesn't make any sense to me at all, but still
> just wondering if missing something, or should I shift over to 3.12 to
> see if if works differently, or just try reinstalling 3.11 from scratch,
> or should I retry the above in something like the VS code console, or a
> different python console, etc.?
Some of the facts, such as HOW the code was being executed were missing
(see earlier request for a cut-down scenario, AND reports from others
saying 'but it works for me').

The idea of importing a module into the REPL and then (repeatedly)
manually entering the code to set-up and execute is unusual (surely type
such into a script (once), and run that (repeatedly). As you say, most
of us would be working from an IDE and hitting 'Run'. Am wondering why
you weren't - but it's not important.

That said, the REPL is the perfect place to learn, experiment, and
prototype - particularly when compared with the facilities of other
language's eco-systems. The entirety of the on-line Tutorial cannot be
wrong! (although, after a quick review, I've failed to see where the
Tutorial mentions the usual development mode, apart from two very brief
asides (the most useful is almost at the very end(?)) - but then (as
they say) the objective is to show the language!

The lesson-learned is that there are different 'environments' and
different ways of building the environment in which the code will run.
That's a valuable lesson, and full of subtlety!

Glad to see that comparing id()s was useful - for diagnosis but not
solution. Other tools might include the locals() and globals()
functions. You may also have detected that many of us try to avoid
globals and the implicit assumptions about the behavior of mutable
collections (eg lists) when treated as 'global'. Then there are
"closures", the "LEGB" rule, namespaces, scope, and ...

--
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
On 2024-03-07, dn via Python-list <python-list@python.org> wrote:

> The idea of importing a module into the REPL and then (repeatedly)
> manually entering the code to set-up and execute is unusual (surely type
> such into a script (once), and run that (repeatedly). As you say, most
> of us would be working from an IDE and hitting 'Run'. Am wondering why
> you weren't - but it's not important.

Unless the code is intended to be used as a module, 'import'ing it into
the REPL doesn't make sense.

A simple example:

---------------------------testit.py------------------------------
x = 'x'
y = 'y'
def foo():
global y
print("hi")
x = 'X'
y = 'Y'
print(x)
print(y)
------------------------------------------------------------------

The usual method to play with that interactively is

$ python -i testit.py
>>> x
'x'
>>> y
'y'
>>> foo()
hi
X
Y
>>> x
'x'
>>> y
'Y'
>>>

As we've seen, doing a 'from testit.py import *' doesn't let you test
what the OP was trying to test. Doing 'import testit.py' gets you
closer, but it's a hassle to test code that way. The right thing to do
is 'python -i <filename>' (or the equivalent button/option in an IDE).

https://docs.python.org/3/tutorial/interpreter.html

If you intended to use testit.py as a module, and wanted to experiment
with its behavior as a module, then go ahead and import it. But, don't
do 'from testit.py import *' until

1. you know how that differs from 'import testit.py'

and

2. you want to use that difference


--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
Thanks again, all.


I think the python -i scoping2.py would have given me a good beginning
as well - will archive that one for use.


And, to maybe explain how I work - not an excuse at all - but, I am
actually 100% blind, so a lot of the IDE's, or their common
means/methods of interaction don't suit me all the time, which is why I
generally work via programmer's text editor interfaces, or treat
something like VS code as such, but then still prefer to run my code via
command line, using pdb to then play around with forms of debugging, etc.


And, yes, also generally prefer to work via classes, modules, etc. at
runtime, but this was more or less mostly testing, which then caused
confusion/interference on my side...LOL!


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


On 2024/03/07 03:55, Grant Edwards via Python-list wrote:
> On 2024-03-07, dn via Python-list <python-list@python.org> wrote:
>
>> The idea of importing a module into the REPL and then (repeatedly)
>> manually entering the code to set-up and execute is unusual (surely type
>> such into a script (once), and run that (repeatedly). As you say, most
>> of us would be working from an IDE and hitting 'Run'. Am wondering why
>> you weren't - but it's not important.
> Unless the code is intended to be used as a module, 'import'ing it into
> the REPL doesn't make sense.
>
> A simple example:
>
> ---------------------------testit.py------------------------------
> x = 'x'
> y = 'y'
> def foo():
> global y
> print("hi")
> x = 'X'
> y = 'Y'
> print(x)
> print(y)
> ------------------------------------------------------------------
>
> The usual method to play with that interactively is
>
> $ python -i testit.py
> >>> x
> 'x'
> >>> y
> 'y'
> >>> foo()
> hi
> X
> Y
> >>> x
> 'x'
> >>> y
> 'Y'
> >>>
>
> As we've seen, doing a 'from testit.py import *' doesn't let you test
> what the OP was trying to test. Doing 'import testit.py' gets you
> closer, but it's a hassle to test code that way. The right thing to do
> is 'python -i <filename>' (or the equivalent button/option in an IDE).
>
> https://docs.python.org/3/tutorial/interpreter.html
>
> If you intended to use testit.py as a module, and wanted to experiment
> with its behavior as a module, then go ahead and import it. But, don't
> do 'from testit.py import *' until
>
> 1. you know how that differs from 'import testit.py'
>
> and
>
> 2. you want to use that difference
>
>
--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
On 06Mar2024 15:12, Jacob Kruger <jacob.kruger.work@gmail.com> wrote:
>So, this does not make sense to me in terms of the following snippet
>from the official python docs page:
>https://docs.python.org/3/faq/programming.html
>
>"In Python, variables that are only referenced inside a function are
>implicitly global. If a variable is assigned a value anywhere within
>the function’s body, it’s assumed to be a local unless explicitly
>declared as global."
>
>So, I would then assume that if I explicitly include a variable name
>inside the global statement, then even just assigning it a new value
>should update the variable in the global context, outside the
>function?

Yes. Note that the "global" namespace is the module in which the
function is defined.

x = 1

def f(n):
global x
x += n

This updates the `x` global variable in the module where `f` was
defined.

If you import `f` and use it in another module it will _still_ update
`x` in the original module namespace.
--
https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference [ In reply to ]
On 2024-03-07, Cameron Simpson via Python-list <python-list@python.org> wrote:

> Yes. Note that the "global" namespace is the module in which the
> function is defined.

One might argue that "global" isn't a good choice for what to call the
scope in question, since it's not global. It's limited to that source
file. It doesn't make sense to me to call a binding "global", when
there can be multile different "global" bindings of the same name.

--
Grant




--
https://mail.python.org/mailman/listinfo/python-list

1 2  View All