ChatGPT解决这个技术问题 Extra ChatGPT

Python function global variables?

I know I should avoid using global variables in the first place due to confusion like this, but if I were to use them, is the following a valid way to go about using them? (I am trying to call the global copy of a variable created in a separate function.)

x = "somevalue"

def func_A ():
   global x
   # Do things to x
   return x

def func_B():
   x = func_A()
   # Do things
   return x

func_A()
func_B()

Does the x that the second function uses have the same value of the global copy of x that func_a uses and modifies? When calling the functions after definition, does order matter?

be careful also not to assume just because you have a variable assigned in your function that python will treat references before the assignment as such. Until the first assignment, if you used x, it would not be the global one, or the local one. You will get the infamous UnboundLocalError exception in your face :)

C
Cristian Ciupitu

If you want to simply access a global variable you just use its name. However to change its value you need to use the global keyword.

E.g.

global someVar
someVar = 55

This would change the value of the global variable to 55. Otherwise it would just assign 55 to a local variable.

The order of function definition listings doesn't matter (assuming they don't refer to each other in some way), the order they are called does.


In the code that I gave, is func_B doing things (1) to the global copy of x (as gotten from func_A), (2) to a local variable x with the same value of the result of func_A, or (3) to a local variable x with no value and (in the eyes of the compiler) no relation to "some value" or the x in func_A?
x in func_B is a local variable that gets its value from the return value of the call to func_A - so I guess that would make it your (2)
ok, let's say x was a random sequence of some kind generated by func_A (i.e. that func_A produced a different x each time it was run.) Would running the program as written make func_b modify a different x than what was originally produced when func_a was called? If so, how can I fix it?
Yes, if func_A changes the global variable during each run and returns it to func_B to use, then func_B will work with a changed value each time. I am not sure about your "how to fix it". You may want to accept the most helpful answer to your current/original question and then consider opening up a different question about what looks like a follow-up question.
Actually it depends what x is. If x is immutable, then the x in func_B will stay in it, because it is declared locally even if they have the same value. This applies to tuples, ints... If it's an instance of a list for example and you do x.append("..."), it's the global variable x that is changed, because the local one references the global one.
j
jdotjdot

Within a Python scope, any assignment to a variable not already declared within that scope creates a new local variable unless that variable is declared earlier in the function as referring to a globally scoped variable with the keyword global.

Let's look at a modified version of your pseudocode to see what happens:

# Here, we're creating a variable 'x', in the __main__ scope.
x = 'None!'

def func_A():
  # The below declaration lets the function know that we
  #  mean the global 'x' when we refer to that variable, not
  #  any local one

  global x
  x = 'A'
  return x

def func_B():
  # Here, we are somewhat mislead.  We're actually involving two different
  #  variables named 'x'.  One is local to func_B, the other is global.

  # By calling func_A(), we do two things: we're reassigning the value
  #  of the GLOBAL x as part of func_A, and then taking that same value
  #  since it's returned by func_A, and assigning it to a LOCAL variable
  #  named 'x'.     
  x = func_A() # look at this as: x_local = func_A()

  # Here, we're assigning the value of 'B' to the LOCAL x.
  x = 'B' # look at this as: x_local = 'B'

  return x # look at this as: return x_local

In fact, you could rewrite all of func_B with the variable named x_local and it would work identically.

The order matters only as far as the order in which your functions do operations that change the value of the global x. Thus in our example, order doesn't matter, since func_B calls func_A. In this example, order does matter:

def a():
  global foo
  foo = 'A'

def b():
  global foo
  foo = 'B'

b()
a()
print foo
# prints 'A' because a() was the last function to modify 'foo'.

Note that global is only required to modify global objects. You can still access them from within a function without declaring global. Thus, we have:

x = 5

def access_only():
  return x
  # This returns whatever the global value of 'x' is

def modify():
  global x
  x = 'modified'
  return x
  # This function makes the global 'x' equal to 'modified', and then returns that value

def create_locally():
  x = 'local!'
  return x
  # This function creates a new local variable named 'x', and sets it as 'local',
  #  and returns that.  The global 'x' is untouched.

Note the difference between create_locally and access_only -- access_only is accessing the global x despite not calling global, and even though create_locally doesn't use global either, it creates a local copy since it's assigning a value.

The confusion here is why you shouldn't use global variables.


I don't think this is very confusing in-practice, you just have to understand python's scoping rules.
k
kindall

As others have noted, you need to declare a variable global in a function when you want that function to be able to modify the global variable. If you only want to access it, then you don't need global.

To go into a bit more detail on that, what "modify" means is this: if you want to re-bind the global name so it points to a different object, the name must be declared global in the function.

Many operations that modify (mutate) an object do not re-bind the global name to point to a different object, and so they are all valid without declaring the name global in the function.

d = {}
l = []
o = type("object", (object,), {})()

def valid():     # these are all valid without declaring any names global!
   d[0] = 1      # changes what's in d, but d still points to the same object
   d[0] += 1     # ditto
   d.clear()     # ditto! d is now empty but it`s still the same object!
   l.append(0)   # l is still the same list but has an additional member
   o.test = 1    # creating new attribute on o, but o is still the same object

N
Noisy_Botnet

You can directly access a global variable inside a function. If you want to change the value of that global variable, use "global variable_name". See the following example:

var = 1
def global_var_change():
      global var
      var = "value changed"
global_var_change() #call the function for changes
print var

Generally speaking, this is not a good programming practice. By breaking namespace logic, code can become difficult to understand and debug.


S
SoloPilot

Here is one case that caught me out, using a global as a default value of a parameter.

globVar = None    # initialize value of global variable

def func(param = globVar):   # use globVar as default value for param
    print 'param =', param, 'globVar =', globVar  # display values

def test():
    global globVar
    globVar = 42  # change value of global
    func()

test()
=========
output: param = None, globVar = 42

I had expected param to have a value of 42. Surprise. Python 2.7 evaluated the value of globVar when it first parsed the function func. Changing the value of globVar did not affect the default value assigned to param. Delaying the evaluation, as in the following, worked as I needed it to.

def func(param = eval('globVar')):       # this seems to work
    print 'param =', param, 'globVar =', globVar  # display values

Or, if you want to be safe,

def func(param = None)):
    if param == None:
        param = globVar
    print 'param =', param, 'globVar =', globVar  # display values

That reminded me of the problem of assigning an empty list as default value. And, as in the example, use is to check if something is None, instead of the normal comparison ==.
M
Marcin

You must use the global declaration when you wish to alter the value assigned to a global variable.

You do not need it to read from a global variable. Note that calling a method on an object (even if it alters the data within that object) does not alter the value of the variable holding that object (absent reflective magic).


This wording is unfortunate. In Python, the value assigned to a variable is a reference, so it is technically correct (and I have no doubt you meant that), but many a reader may interpret "alter the value" as "mutate the object", which is not the case -- xs.append(xs.pop(0)) works just fine without global xs.
@delnan My answer is carefully worded, but I will clarify.