3

First, I fully understand what global statement means and how to use.

Now, let's look at this:

x = 100
def f():
    global x
    global xxx
    x = 99
    return x

print(f())
# >>> 99
print(x)
# >>> 99

You can see that by using global x, I successfully changed the value of x in the global environment.

But xxx does not exist at all, why am I allowed to global it and it won't even bring any error even if the function is executed?

jxie0755
  • 1,682
  • 1
  • 16
  • 35
  • 1
    I THINK that `global xxx` is just a redundant statement but since its a valid python code the python interpreter merely ignores it like a mother ignores your childish mistakes. I could be wrong though. – Ubdus Samad Jul 11 '18 at 14:49
  • But I thought python check all the variable bounding situation in compiling before running at all, and if there is a bounding error, then it won't execute? – jxie0755 Jul 11 '18 at 14:50
  • You can initialize variables with `global` by just giving them a name, although I am not sure what the default behavior is for these variables. Oddly enough I cannot find anything in the Python 3 docs about the `global` keyword and its use. – Engineero Jul 11 '18 at 14:51
  • I amend my previous statement: you are allowed to declare globals with a naked `global x`, but you can't access them if you haven't assigned anything to them. I think the interpreter just throws this out and ignores it. – Engineero Jul 11 '18 at 14:54

1 Answers1

11

global x does not define, declare, or otherwise create x. It simply states that if and when x is assigned to in the current function scope (whether that assignment comes before or after the global statement, which is why it is strongly recommended that global statements be used at the beginning of the function), the assignment is made to a global variable of that name, not a local variable. The actual creation is still the job of an actual assignment.

Put another way, global doesn't generate any byte code by itself; it simply modifies what byte code other assignment statements might generate. Consider these two functions:

def f():
    global x
    x = 99

def g():
    x = 99

The only difference in the byte code for these two functions is that f use STORE_GOBAL as a result of the global statement, while g uses STORE_FAST.

>>> dis.dis(f)
  5           0 LOAD_CONST               1 (99)
              3 STORE_GLOBAL             0 (x)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE
>>> dis.dis(g)
  8           0 LOAD_CONST               1 (99)
              3 STORE_FAST               0 (x)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE

If you were to add an "unused" global statement, such as in

def h():
    global xxx
    x = 99

the resulting byte code is indistinguishable from g:

>>> dis.dis(h)
  3           0 LOAD_CONST               1 (99)
              2 STORE_FAST               0 (x)
              4 LOAD_CONST               0 (None)
              6 RETURN_VALUE
chepner
  • 497,756
  • 71
  • 530
  • 681
  • can you check this one out, and maybe explain why nonlocal behaves differently?https://stackoverflow.com/questions/51287522/nonlocal-statement-got-checked-without-running-the-function-in-python/51287668?noredirect=1#comment89553896_51287668 – jxie0755 Jul 11 '18 at 14:53
  • 1
    `nonlocal` doesn't fall back to the global scope; it only looks in other scopes *between* the current scope and the global scope. Because `x` did not exist in the scope of `f` (the only scope between `g`'s local scope and the global scope), the lookup for `x` on the right-hand side of `x = x * 99` failed. Note that the use of `nonlocal` also allowed this to be caught by the parser as a `SyntaxError`, rather than a lookup error. – chepner Jul 11 '18 at 14:58
  • When `g` is being defined, the scope of `f` has already been established, allowing the parser to recognize if `x` is in scope, even if `f` itself doesn't actually provide an assignment until *after* `def g` is parsed. (I'm assuming it's not strictly a syntax error in the sense of the code not being parseable, but rather a static analysis step taken after the source for `f` is actually fully parsed.) – chepner Jul 11 '18 at 15:01