• Variable scope inside and outside functions - global statement beingoverridden by assignation unless preceded by reference

    From Jacob Kruger@jacob.kruger.work@gmail.com to comp.lang.python on Tue Mar 5 20:13:21 2024
    From Newsgroup: comp.lang.python

    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..."


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From ram@ram@zedat.fu-berlin.de (Stefan Ram) to comp.lang.python on Tue Mar 5 18:46:31 2024
    From Newsgroup: comp.lang.python

    Jacob Kruger <jacob.kruger.work@gmail.com> wrote or quoted:
    l_servers = []
    ...
        global l_servers
    That should, in theory, mean that if I assign a value to that variable
    inside one of the functions, it should reflect globally?

    Yes.

    l =[ 1, 2, 3 ]

    def f():
    global l
    l =[ 2, 3, 4 ]

    f()

    print( l )
    # [2, 3, 4]
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From ram@ram@zedat.fu-berlin.de (Stefan Ram) to comp.lang.python on Tue Mar 5 23:12:24 2024
    From Newsgroup: comp.lang.python

    Grant Edwards <grant.b.edwards@gmail.com> wrote or quoted:
    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

    |If a local variable is defined in a block,
    The Python Language Reference, Release 3.13.0a0,
    4.2.2 Resolution of names, p1

    |checking the module’s namespace for a variable named __all__;
    |if defined, it must be a sequence of strings
    ibid., 7.11

    |class variable A variable defined in a class
    ibid., Appendix A
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From ram@ram@zedat.fu-berlin.de (Stefan Ram) to comp.lang.python on Wed Mar 6 13:17:45 2024
    From Newsgroup: comp.lang.python

    Jacob Kruger <jacob.kruger.work@gmail.com> writes: 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?

    I can only guess that after "do_it" you might have inadvertently
    restarted the interpreter.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From ram@ram@zedat.fu-berlin.de (Stefan Ram) to comp.lang.python on Wed Mar 6 16:40:26 2024
    From Newsgroup: comp.lang.python

    Jacob Kruger <jacob.kruger.work@gmail.com> wrote or quoted:
    from scoping2 import *

    Now, "dt_expiry" exists in /two/ modules: In "scoping2" and in the
    current module (as a copy). To avoid this, "import scoping2" instead.

    print(dt_expiry)
    1970-01-01 00:00:00+00:00
    do_it()
    2024-03-06 18:12

    This changes the variable "dt_expiry" in "scoping2", but not the
    copy (also named "dt_expiry") in the current module.

    print(dt_expiry)
    1970-01-01 00:00:00+00:00

    This prints "dt_expiry" from the current module, not from "scoping2".

    To avoid this, replace "from scoping2 import *" by "import scoping2"
    and replace the "dt_expiry" in the two print statements by
    "scoping2.dt_expiry".
    --- Synchronet 3.20a-Linux NewsLink 1.114