It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
There is this code:
def f():
x = m
m = 2
def g():
x = m
f() # UnboundLocalError: local variable 'm' referenced before assignment
g() # NameError: global name 'm' is not defined
In both function bodies there is used variable m which is not defined when used but the error messages are different. Do Python know what variables are defined in function before using them (like in function f)? Why the error messages are different?
If there is an assignment to a variable anywhere in a function, then it is considered a local variable everywhere in that function. This means that for the function f(), even though the assignment to m happens after the attempt to access m, the line x = m will only look for the name m within the local scope. This is why the error message for f() refers to m as a local variable.
In the function g() there is no assigment to m, so the line x = m will look for m using the order described here:
the innermost scope, which is searched first, contains the local
names
the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names
the next-to-last scope contains the current module’s global names
the outermost scope (searched last) is the namespace containing built-in names
The error message for g(), "global name 'm' is not defined", refers to the global scope because that is the last location that was searched (except built-in, but it would be confusing to have a message like "the name 'm' was not found in the built-in namespace").
Note that you can use the global or nonlocal statements to change this behavior (nonlocal only exists in Python 3.x).
Python checks it as soon as you call it.
When importing, and typing directly into the interpreter, it only cares if you broke any syntax rules. it doesnt care about locals or globals at this level.
>>> def foo():
... print locals()
... bar = 34
... print locals()
... DIP = SET
...
>>>
>>> foo()
{}
{'bar': 34}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in foo
NameError: global name 'SET' is not defined
it runs from top to bottom, and checks locals() and globals() if it sees that variable then its okay and does whatever with it.
it even works with definitions and sub definitions.. or anything else you are assigning
>>> def foo():
... bar()
... def bar():
... print("never gonna give you up")
...
>>>
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'bar' referenced before assignment
Yes. If you assign to a variable at any point in a function (without using the global keyword), Python treats all references to that name in the function as local.
When you execute a function, you actually invoke __call()__ on a function object.
The function object is created in the scripts global namespace when the script is parsed.
Created, but not executed.
As part of the parsing process, the objects namespace is computed. So the interpreter can actually know which variable exists and when.
def f():
x = m
m = 2
When the above function parsed python thinks that m is local variable as it finds m = 2, so when the function is actually called x = m will raise error as m is not defined yet in local scope.
def g():
x = m
In this python thinks that m is going to be some value from the global scope, it searches the global namespace first and then built-ins, but when m is not found anywhere the error is raised.
>>> m = 1
>>> def g():
x = m
>>> g() #works fine because `m` is found in global scope
>>> def g():
x = sum
>>> g() # sum is found in built-ins
To modify a global variable use global:
>>> m = 1
>>> def g():
global m
m += 1
...
>>> g()
>>> m
2
You need to use global m inside the function
Related
This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 7 months ago.
I was learning about closures in Lua and came accross this code that works in Lua:
function newcounter()
local i = 0
function dummy()
i = i + 1
return i
return dummy
x = newcounter()
print(x())
-- this outputs 1, i.e., dummy uses the i variable from its enclosing function newcounter
I thought Python also supports a similar closure. So I tried the following code in Python3:
def nc():
i = 0
def dummy():
i = i + 1
return i
return dummy
x = nc()
print(x())
However, when I run the above Python code, I get the error that i is accessed before being assigned!
Traceback (most recent call last):
File "/tmp/test.py", line 9, in <module>
print(x())
File "/tmp/test.py", line 4, in dummy
i = i + 1
UnboundLocalError: local variable 'i' referenced before assignment
Does this mean Python does not support closures? Or am I misunderstanding something about closures?
Python decides the scope of variables based on where it finds assignments to them. Because you have an assignment to i in the form i = ..., i will be a local variable scoped to dummy by default, but you can override that with a nonlocal statement:
def nc():
i = 0
def dummy():
nonlocal i
i = i + 1
return i
return dummy
x = nc()
print(x())
So yes, Python has closures.
Assigning to a name within a Python function makes it local by default, from the beginning of the function to the end. If you want to assign to names while having them remain tied to the closure scope, you must explicitly declare said name nonlocal:
def nc():
i = 0
def dummy():
nonlocal i # Makes code work as expected by forcing loads and stores to apply to
# closed-upon i
i = i + 1
return i
return dummy
Python supports closures. The issue you're dealing with here has to do with how scoping works, which is explained here: UnboundLocalError on local variable when reassigned after first use. Note that you can get the same error by referencing a global variable.
Here's an example closure:
def nc(i):
def dummy():
return i
return dummy
x = nc(9)
i = 8
print(x()) # -> 9
This question already has answers here:
nonlocal keyword in Python 2.x
(10 answers)
Closed 6 months ago.
Edit:
See my full answer at the bottom of this question.
tl;dr answer: Python has statically nested scopes. The static
aspect can interact with the implicit variable declarations, yielding non-obvious results.
(This can be especially surprising because of the language's generally dynamic nature).
I thought I had a pretty good handle on Python's scoping rules, but this problem has me thoroughly stymied, and my google-fu has failed me (not that I'm surprised - look at the question title ;)
I'm going to start with a few examples that work as expected, but feel free to skip to example 4 for the juicy part.
Example 1.
>>> x = 3
>>> class MyClass(object):
... x = x
...
>>> MyClass.x
3
Straightforward enough: during class definition we're able to access the variables defined in the outer (in this case global) scope.
Example 2.
>>> def mymethod(self):
... return self.x
...
>>> x = 3
>>> class MyClass(object):
... x = x
... mymethod = mymethod
...
>>> MyClass().mymethod()
3
Again (ignoring for the moment why one might want to do this), there's nothing unexpected here: we can access functions in the outer scope.
Note: as Frédéric pointed out below, this function doesn't seem to work. See Example 5 (and beyond) instead.
Example 3.
>>> def myfunc():
... x = 3
... class MyClass(object):
... x = x
... return MyClass
...
>>> myfunc().x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in myfunc
File "<stdin>", line 4, in MyClass
NameError: name 'x' is not defined
This is essentially the same as example 1: we're accessing the outer scope from within the class definition, just this time that scope isn't global, thanks to myfunc().
Edit 5: As #user3022222 pointed out below, I botched this example in my original posting. I believe this fails because only functions (not other code blocks, like this class definition) can access variables in the enclosing scope. For non-function code blocks, only local, global and built-in variables are accessible. A more thorough explanation is available in this question
One more:
Example 4.
>>> def my_defining_func():
... def mymethod(self):
... return self.y
... class MyClass(object):
... mymethod = mymethod
... y = 3
... return MyClass
...
>>> my_defining_func()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in my_defining_func
File "<stdin>", line 5, in MyClass
NameError: name 'mymethod' is not defined
Um...excuse me?
What makes this any different from example 2?
I'm completely befuddled. Please sort me out.
Thanks!
P.S. on the off-chance that this isn't just a problem with my understanding, I've tried this on Python 2.5.2 and Python 2.6.2. Unfortunately those are all I have access to at the moment, but they both exhibit the same behaviour.
Edit
According to http://docs.python.org/tutorial/classes.html#python-scopes-and-namespaces: at any time during execution, there are at least three nested scopes whose namespaces are directly accessible:
the innermost scope, which is
searched first, contains the local
names
the scopes of any enclosing
functions, which are searched
starting with the nearest enclosing
scope, contains non-local, but also
non-global names
the next-to-last scope contains the
current module’s global names
the outermost scope (searched last)
is the namespace containing built-in
names
#4. seems to be a counter-example to the second of these.
Edit 2
Example 5.
>>> def fun1():
... x = 3
... def fun2():
... print x
... return fun2
...
>>> fun1()()
3
Edit 3
As #Frédéric pointed out the assignment of to a variable of the same name as it has in the outer scope seems to "mask" the outer variable, preventing the assignment from functioning.
So this modified version of Example 4 works:
def my_defining_func():
def mymethod_outer(self):
return self.y
class MyClass(object):
mymethod = mymethod_outer
y = 3
return MyClass
my_defining_func()
However this doesn't:
def my_defining_func():
def mymethod(self):
return self.y
class MyClass(object):
mymethod_temp = mymethod
mymethod = mymethod_temp
y = 3
return MyClass
my_defining_func()
I still don't fully understand why this masking occurs: shouldn't the name binding occur when the assignment happens?
This example at least provides some hint (and a more useful error message):
>>> def my_defining_func():
... x = 3
... def my_inner_func():
... x = x
... return x
... return my_inner_func
...
>>> my_defining_func()()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in my_inner_func
UnboundLocalError: local variable 'x' referenced before assignment
>>> my_defining_func()
<function my_inner_func at 0xb755e6f4>
So it appears that the local variable is defined at function creation (which succeeds), resulting in the local name being "reserved" and thus masking the outer-scope name when the function is called.
Interesting.
Thanks Frédéric for the answer(s)!
For reference, from the python docs:
It is important to realize that scopes
are determined textually: the global
scope of a function defined in a
module is that module’s namespace, no
matter from where or by what alias the
function is called. On the other hand,
the actual search for names is done
dynamically, at run time — however,
the language definition is evolving
towards static name resolution, at
“compile” time, so don’t rely on
dynamic name resolution! (In fact,
local variables are already determined
statically.)
Edit 4
The Real Answer
This seemingly confusing behaviour is caused by Python's statically nested scopes as defined in PEP 227. It actually has nothing to do with PEP 3104.
From PEP 227:
The name resolution rules are typical
for statically scoped languages [...]
[except] variables are not declared.
If a name binding operation occurs
anywhere in a function, then that name
is treated as local to the function
and all references refer to the local
binding. If a reference occurs before
the name is bound, a NameError is
raised.
[...]
An example from Tim Peters demonstrates the potential pitfalls of
nested scopes in the absence of declarations:
i = 6
def f(x):
def g():
print i
# ...
# skip to the next page
# ...
for i in x: # ah, i *is* local to f, so this is what g sees
pass
g()
The call to g() will refer to the variable i bound in f() by the for
loop. If g() is called before the loop is executed, a NameError will
be raised.
Lets run two simpler versions of Tim's example:
>>> i = 6
>>> def f(x):
... def g():
... print i
... # ...
... # later
... # ...
... i = x
... g()
...
>>> f(3)
3
when g() doesn't find i in its inner scope, it dynamically searches outwards, finding the i in f's scope, which has been bound to 3 through the i = x assignment.
But changing the order the final two statements in f causes an error:
>>> i = 6
>>> def f(x):
... def g():
... print i
... # ...
... # later
... # ...
... g()
... i = x # Note: I've swapped places
...
>>> f(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in f
File "<stdin>", line 3, in g
NameError: free variable 'i' referenced before assignment in enclosing scope
Remembering that PEP 227 said "The name resolution rules are typical for statically scoped languages", lets look at the (semi-)equivalent C version offer:
// nested.c
#include <stdio.h>
int i = 6;
void f(int x){
int i; // <--- implicit in the python code above
void g(){
printf("%d\n",i);
}
g();
i = x;
g();
}
int main(void){
f(3);
}
compile and run:
$ gcc nested.c -o nested
$ ./nested
134520820
3
So while C will happily use an unbound variable (using whatever happens to have been stored there before: 134520820, in this case), Python (thankfully) refuses.
As an interesting side-note, statically nested scopes enable what Alex Martelli has called "the single most important optimization the Python compiler does: a function's local variables are not kept in a dict, they're in a tight vector of values, and each local variable access uses the index in that vector, not a name lookup."
That's an artifact of Python's name resolution rules: you only have access to the global and the local scopes, but not to the scopes in-between, e.g. not to your immediate outer scope.
EDIT: The above was poorly worded, you do have access to the variables defined in outer scopes, but by doing x = x or mymethod = mymethod from a non-global namespace, you're actually masking the outer variable with the one you're defining locally.
In example 2, your immediate outer scope is the global scope, so MyClass can see mymethod, but in example 4 your immediate outer scope is my_defining_func(), so it can't, because the outer definition of mymethod is already masked by its local definition.
See PEP 3104 for more details about nonlocal name resolution.
Also note that, for the reasons explained above, I can't get example 3 to run under either Python 2.6.5 or 3.1.2:
>>> def myfunc():
... x = 3
... class MyClass(object):
... x = x
... return MyClass
...
>>> myfunc().x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in myfunc
File "<stdin>", line 4, in MyClass
NameError: name 'x' is not defined
But the following would work:
>>> def myfunc():
... x = 3
... class MyClass(object):
... y = x
... return MyClass
...
>>> myfunc().y
3
This post is a few years old, but it is among the rare ones to discuss the important problem of scope and static binding in Python. However, there is an important misunderstanding of the author for example 3 that might confuse readers. (do not take as granted that the other ones are all correct, it is just that I only looked at the issues raised by example 3 in details).
Let me clarify what happened.
In example 3
def myfunc():
x = 3
class MyClass(object):
x = x
return MyClass
>>> myfunc().x
must return an error, unlike what the author of the post said. I believe that he missed the error because in example 1 x was assigned to 3 in the global scope. Thus a wrong understanding of what happened.
The explanation is extensively described in this post
How references to variables are resolved in Python
This question already has answers here:
Is it possible to modify a variable in python that is in an outer (enclosing), but not global, scope?
(9 answers)
Closed 5 months ago.
I am confused with the global keyword behavior in below code snippet, I was expecting 30, 30, 30 in all 3 prints.
def outer_function():
#global a ###commented intentionally
a = 20
def inner_function():
global a
a = 30
print('a =',a)
inner_function()
print('a =',a)
a = 10
outer_function()
print('a =',a)
#Output:
#30
#20 #Expecting 30 here
#30
All the confusion coming from "global a" after outer function definition. As my understanding at this point of time is " All the reference and assignment to variable become globally reflected on declaration of global keyword on that variable". If I am uncommenting that first global statement I am getting expected output 30,30,30.
Why global declaration inside inner_function and value change does not reflect on 2nd print i:e to outer_function(or outer scope), whereas got reflected in global namespace.
A common acronym to be familiar with is LEGB:
Local
Enclosed
Global
Built-in
This is the order in which Python will search the namespaces to find variable assignments.
Local
The local namespace is everything that happens within the current code block. Function definitions contain local variables that are the first thing that is found when Python looks for a variable reference. Here, Python will look in the local scope of foo first, find x with the assignment of 2 and print that. All of this happens despite x also being defined in the global namespace.
x = 1
def foo():
x = 2
print(x)
foo()
# prints:
2
When Python compiles a function, it decides whether each of the variables within the definition code block are local or global variables. Why is this important? Let's take a look at the same definition of foo, but flip the two lines inside of it. The result can be surprising
x = 1
def foo():
print(x)
x = 2
foo()
# raises:
UnboundLocalError: local variable 'x' referenced before assignment
This error occurs because Python compiles x as a local variable within foo due to the assignment of x = 2.
What you need to remember is that local variables can only access what is inside of their own scope.
Enclosed
When defining a multi-layered function, variables that are not compiled as local will search for their values in the next highest namespace. Here is a simple example.
x = 0
def outer_0():
x = 1
def outer_1():
def inner():
print(x)
inner()
outer_1()
outer_0()
# print:
1
When inner() is compiled, Python sets x as a global variable, meaning it will try to access other assignments of x outside of the local scope. The order in which Python searches for a value of x in moving upward through the enclosing namespaces. x is not contained in the namespace of outer_1, so it checks outer_0, finds a values and uses that assignment for the x within inner.
x --> inner --> outer_1 --> outer_0 [ --> global, not reached in this example]
You can force a variable to not be local using the keywords nonlocal and global (note: nonlocal is only available in Python 3). These are directives to the compiler about the variable scope.
nonlocal
Using the nonlocal keyword tells python to assign the variable to first instance found as it moves upward through the namespaces. Any changes made to the variable will be made in the variable's original namespace as well. In the example below, when 2 is assigned x, it is setting the value of x in the scope of outer_0 as well.
x = 0
def outer_0():
x = 1
def outer_1():
def inner():
nonlocal x
print('inner :', x)
x = 2
inner()
outer_1()
print('outer_0:', x)
outer_0()
# prints:
inner : 1
outer_0: 2
Global
The global namespace is the highest level namespace that you program is running in. It is also the highest enclosing namespace for all function definitions. In general it is not good practice to pass values in and out of variables in the global namespace as unexpected side effects can occur.
global
Using the global keyword is similar to non-local, but instead of moving upward through the namespace layers, it only searches in the global namespace for the variable reference. Using the same example from above, but in this case declaring global x tells Python to use the assignment of x in the global namespace. Here the global namespace has x = 0:
x = 0
def outer_0():
x = 1
def outer_1():
def inner():
global x
print('inner :', x)
inner()
outer_1()
outer_0()
# prints:
0
Similarly, if a variable is not yet defined in the global namespace, it will raise an error.
def foo():
z = 1
def bar():
global z
print(z)
bar()
foo()
# raises:
NameError: name 'z' is not defined
Built-in
Last of all, Python will check for built-in keywords. Native Python functions such as list and int are the final reference Python checks for AFTER checking for variables. You can overload native Python functions (but please don't do this, it is a bad idea).
Here is an example of something you SHOULD NOT DO. In dumb we overload the the native Python list function by assigning it to 0 in the scope of dumb. In the even_dumber, when we try to split the string into a list of letters using list, Python will find the reference to list in the enclosing namespace of dumb and try to use that, raising an error.
def dumb():
list = 0
def even_dumber():
x = list('abc')
print(x)
even_dumber()
dumb()
# raises:
TypeError: 'int' object is not callable
You can get back the original behavior by referencing the global definition of list using:
def dumb():
list = [1]
def even_dumber():
global list
x = list('abc')
print(x)
even_dumber()
dumb()
# returns:
['a', 'b', 'c']
But again, DO NOT DO THIS, it is bad coding practice.
I hope this helps bring to light some of how the namespaces work in Python. If you want more information, chapter 7 of Fluent Python by Luciano Ramalho has a wonderful in-depth walkthrough of namespaces and closures in Python.
From the documentation:
The global statement is a declaration which holds for the entire
current code block. It means that the listed identifiers are to be
interpreted as globals.
Note it only applies to current code block. So the global in inner_function only applies within inner_function. Outside of it, the identifier is not global.
Note how “identifier” is not the same as “variable”. So what it tells the interpreter is “when I use identifier a within this code block, do not apply normal scope resolution, I actually mean the module-level variable, ”.
Just uncomment your global command in the outer_function, otherwise you're declaring a local variable with value 20, changing a global variable then printing that same local variable.
It's not a good idea use global variabilities. If you want only reset the value of a variable, you just use this lines:
def outer_function():
a = 20
def inner_function():
a = 30
print('a =',a)
return a
a = inner_function()
print('a =',a)
return a
a = 10
a = outer_function()
print('a =',a)
gCharlie = 0
gJeff = 0
def Bob ():
Charlie = gCharlie
Jeff = gJeff
Number = int(input("Hello and Welcome to Charlie's Number Guessing Game. Enter a nonnegative number from 0 to 10 not counting 0. "))
This code gives me this error in Python 3.2:
UnboundLocalError: local variable 'gCharlie' referenced before assignment
What does this local variable error mean?
inside the Scope of your function you must have reassigned gJeff and gCharlie, which created them as new local variables. To tell python that you're using the globals, change the top of your function to look like this.
def Bob():
global gCharlie
global gJeff
Charlie=gCharlie
without telling python that you're using the globals, it tries to reference local gCharlie and gJeff variables, which as it says, have not been assigned at that point in your function. The reason people are getting it to work is because they're using only the code you've posted. You can reference globals without explicitly saying so ONLY if you don't change their values within the function referencing them.
As a rule python searches in this order for a variable name: local scope, any def it is nested inside of, global, built ins. Bbecause gJeff and gCharlie are local variables in your function, it stops there, unless you tell it otherwise.
If you want to see this in action try to look at this
x=5
def useX():
x=0 #this is a local variable
print "in function: ", x
def main():
print "in main(1): ", x
useX()
print "in main(2): ", x
main()
this will output
in main(1): 5
in function: 0
in main(2): 5
because within the function, x is created as a new local variable. Adding a global x statement to the useX function would change the last line to print "0" instead of "5"
It might be due to there is gCharlie = inside a function (note: the first letter is g).
Use parameters instead of globals:
def bob(charlie=0, jeff=0):
number = int(input("..."))
# ...
bob(charlie=3)
It means that you're assigning to gCharlie in the part of the function you didn't show, and so the Python compiler has marked it as a local variable. As such, you're accessing it before it exists. Use nonlocal or global to solve.
Two previous answers here are correct, but both are a bit unclear. I'll show with some examples:
The code you show will work fine:
>>> gCharlie = "Global!"
>>>
>>> def foo():
... print(gCharlie)
...
>>> foo()
Global!
>>> print(gCharlie)
Global!
So that's not the problem at all. However, you can't assign global variables inside a function:
>>> gCharlie = "Global!"
>>> def foo():
... gCharlie = "Local!"
... print(gCharlie)
...
>>> foo()
Local!
>>> print(gCharlie)
Global!
As you see, the global variable gCharlie did not change. This is because you did not modify it, you created a new local variable, with the same name. And this is the cause of the error:
>>> gCharlie = "Global!"
>>> def foo():
... oldCharlie = gCharlie
... gCharlie = "Local!"
... print(gCharlie)
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'gCharlie' referenced before assignment
The hint is in the error. It says local variable gCharlie. The problem is not the inability to access the global gCharlie, but that the local one hasn't been created yet.
The fix is to specify that you don't want to create a local variable, but that you want to modify the global one. You do this with the global keyword.
>>> gCharlie = "Global!"
>>> def foo():
... global gCharlie
... oldCharlie = gCharlie
... gCharlie = "Local!"
... print(gCharlie)
...
>>> foo()
Local!
>>> print(gCharlie)
Local!
As you see now, you modified the global variable.
That said, global variables are usually a bad idea. Avoid them. Try to pass in the variables as parameters instead.
I am learning Python and just had this question. It possibly has no practical worth, I'm asking this out maybe because of a pedantic curiosity.
I have a function:
def f():
x = 12 #this is a local variable
global x #this is a global I declared before
x = 14 #changes global x
<How can I return the local x?>
I'm aware that this is ugly and I do get a Syntax Warning. Just wanted to know how to "get back" my local variable.
Thanks to everyone.
Your code isn't doing what you think it is and there's no way to change it do what you describe. You can't "revert" what globals does since it has no effect at run time.
The global keyword is interpreted at compile time so in the first line of f() where you set x = 12 this is modifying the global x since the compiler has decided the x refers to the x in the global namespace throughout the whole function, not just after the global statement.
You can test this easily:
>>> def g():
... x = 12
... y = 13
... global x
... print "locals:",locals()
...
<stdin>:4: SyntaxWarning: name 'x' is assigned to before global declaration
>>> g()
locals: {'y': 13}
The locals() function gives us a view of the local namespace and we can see that there's no x in there.
The documentation says the following:
Names listed in a global statement must not be used in the same code block textually preceding that global statement.
Names listed in a global statement must not be defined as formal parameters or in a for loop control target, class definition, function definition, or import statement.
The current implementation does not enforce the latter two restrictions, but programs should not abuse this freedom, as future implementations may enforce them or silently change the meaning of the program.
Just give the local variable a different name.
I very much doubt that it can be done.
>>> x = 1
>>> def f():
... x = 12
... global x
... print x
...
<stdin>:3: SyntaxWarning: name 'x' is assigned to before global declaration
>>> f()
12
>>> x
12
As you can see, even without an explicit assignment to x after the global keyword, python syncs up the the values of the two. To see why, you have to disassemble it.
>>> dis.dis(f) # different f with print statement removed for clarity
2 0 LOAD_CONST 1 (12)
3 STORE_GLOBAL 0 (x)
3 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
>>>
The global keyword isn't represented here at all but the assignment statement gets compiled as STORE_GLOBAL. After you do it, it's done. Use globals with care and the global keyword with greater care.
It is not possible to undo the effect of a global statement.
A global statement applies for the entire duration of the function in which it appears, regardless of where in the function it is, and regardless of whether it's executed. So, for example, in the assignment in the following function:
def f():
x = 3
if False:
global x
x is still treated as global.
So it wouldn't make sense to have another statement to undo its effect afterwards, since a global "statement" is not so much a statement, that is executed at some point during the function, as a declaration about the behavior of the function as a whole.