-2
VAR = 123

def func(param=False):
    if param:
        VAR = 456
    return VAR

func(True)  # 456
func()      # UnboundLocalError: ...

NB: I do not need to change the global variable!

I expect that for the first call the function returns a local variable shadowing the global – that actually works. And for for the second call I expect the function to return the global variable – that leads to exception.

Help me please to understand. Why the interpreter doesn't let me conditionally use both global variable or local?

I suppose that during the second call the local variable shouldn't be declared and so shouldn't shadow the global variable. Then why it leads to exception?

Gennadiy
  • 192
  • 10
  • you have `VAR = ...` without `global VAR` so it think you want to use all time local variable. You should use `a = VAR` at start and `a = 456` and `return a` – furas May 27 '22 at 02:52
  • Does this answer your question? [Using global variables in a function](https://stackoverflow.com/questions/423379/using-global-variables-in-a-function) – Rizquuula May 27 '22 at 02:56
  • @furas, I don't want to change the value of global variable, I want to refer to the global variable **or** to the local variable depending on condition – Gennadiy May 27 '22 at 03:23
  • @Rizquuula, no, because there's nothing about conditions. In the second call the local variable shouldn't be declared and so shouldn't shadow the global variable. Then why it leads to exception? – Gennadiy May 27 '22 at 03:25
  • The name is always going to be the global. The only difference with the parameter is that you're CHANGING the global. Add the `global` statement and it will work fine. Without that, `VAR` in the function is always considered to be a local. – Tim Roberts May 27 '22 at 03:26
  • @Tim Roberts, no changing, only shadowing – Gennadiy May 27 '22 at 03:27
  • 1
    Do you understand how the interpreter read the code before executing it? There is similar workaround in the answer here https://stackoverflow.com/questions/70514761/how-does-python-interpreter-actually-interpret-a-program – Rizquuula May 27 '22 at 03:32
  • @Rizquuula, yes, but shouldn't the function object be re-compiled depending on condition? – Gennadiy May 27 '22 at 03:39
  • 2
    @Gennadiy -- No. It's a design choice, and what you're describing is simply not how Python works. There is a rule. **IF** you have code in a function that COULD write to a variable, then the variable is considered local to the function throughout the function. The decision is made at compile time, NOT at runtime. You need a `global` declaration to override that. Your expectations are irrelevant -- this is how Python works. – Tim Roberts May 27 '22 at 06:53

2 Answers2

2

You can't do conditional shadowing. You can use only local variable or only global variable.

And when you use VAR = ... then it automatically assume that you use local variable.

You have to create other local variable and assign global value or new value.

VAR = 123

def func(param=False):
    result = VAR
    if param:
        result = 456
    return result

print(func(True))  # 456
print(func())      # 123

And frankly, for me this is more readable and doesn't make confusion if I still use local or global variable.

furas
  • 134,197
  • 12
  • 106
  • 148
0

When you define VAR inside the function python thinks that is the "version" of VAR that you want; in other words, you are defining a local inside the "if" statement, so python references that local variable.

def func(param=False):
    if param:
        return VAR
    return VAR

This doesn't cause any issues because you aren't defining the local VAR. When True is passed in it works because you define the local. But since that local is in the function that's what scope it uses.

def func(param=False):
    if param:
        VAR
    return VAR

func()

The code above functions fine because you aren't define a local bound variable.

From the comments on here I Read This and it python is put into byte code then run on a virtual machine. So the variable locations needs to be defined before runtime, then during runtime the interpreter knows which way to go.

taylorSeries
  • 505
  • 2
  • 6
  • 18